chore: add a shared subprocess execution module to private-tools - #1763
Merged
Conversation
…e-tools Adds @aws-cdk/private-tools/lib/subprocess, one audited implementation of child-process execution for the toolchain, with exactly two shapes: - run(argv) / runSync(argv): argv-array spawn, never a shell. Windows .cmd/.bat shims are resolved by cross-spawn (modern Node refuses to spawn batch shims directly, CVE-2024-27980). Shell injection is impossible by construction, so no argument escaping exists at all. - runUserCommandLine(line): the only path to a shell, reserved for command lines the user authored themselves (cdk.json app command, --browser). Deliberately has no argv form. Also included: - renderForDisplay(argv): display-only quoting for logs, allowlist-based - SubprocessError with a kind discriminant (spawn-failed|exited|killed) - Stateful UTF-8 decoding (multi-byte chars split across pipe chunks), stdin EPIPE tolerance, line-buffered output delivery, capture / inherit-stderr / inherit stdio modes, opt-out output collection Consumers are migrated in a follow-up PR.
Contributor
Dependency ReviewThe following issues were found:
License Issuespackages/@aws-cdk/private-tools/package.json
OpenSSF Scorecard
Scanned Files
|
3 tasks
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new shared subprocess execution module under @aws-cdk/private-tools intended to unify how the CDK toolchain spawns child processes, with a clear trust model split between argv-based execution (run/runSync, no shell) and user-authored command lines (runUserCommandLine, shell). This PR is foundational (no consumer migrations yet) and focuses on correctness, security boundaries, and test coverage.
Changes:
- Introduces
packages/@aws-cdk/private-tools/lib/subprocesswithrun(),runSync(),runUserCommandLine(),SubprocessError, and display-only rendering utilities. - Adds comprehensive unit tests for piping, timeouts, failure classification, UTF-8 chunk decoding, line buffering, and Windows
.cmdshim behavior. - Wires in
cross-spawn(and types) via projen + package metadata updates.
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| yarn.lock | Adds cross-spawn and @types/cross-spawn entries to the lockfile. |
| packages/@aws-cdk/private-tools/tsconfig.json | Includes cross-spawn typings due to restricted types list. |
| packages/@aws-cdk/private-tools/test/subprocess/subprocess.test.ts | New unit test suite covering subprocess behaviors and edge cases. |
| packages/@aws-cdk/private-tools/package.json | Adds cross-spawn (runtime) and @types/cross-spawn (dev) dependencies. |
| packages/@aws-cdk/private-tools/lib/subprocess/index.ts | Implements the shared subprocess execution module and error model. |
| packages/@aws-cdk/private-tools/.projen/tasks.json | Updates dependency task filters to include @types/cross-spawn. |
| packages/@aws-cdk/private-tools/.projen/deps.json | Records new runtime/build deps for projen-managed dependency tracking. |
| .projenrc.ts | Adds a subprocess tool definition to the private-tools tool set (deps/devDeps). |
Comments suppressed due to low confidence (1)
packages/@aws-cdk/private-tools/lib/subprocess/index.ts:303
- This comment says DISPLAY_SAFE contains characters that “never need quoting … on any platform”, but Windows intentionally treats
%as unsafe (cmd.exe expansion) and forces quoting via a special-case check. Updating the comment would prevent future changes from accidentally reintroducing%as a Windows-safe character based on this docstring.
* Characters that never need quoting for display, on any platform.
*
* Everything else — including every POSIX and cmd.exe metacharacter (`;`, `|`,
* `&`, `<`, `>`, `(`, `)`, backtick, `*`, `^`, `%`, quotes, whitespace, …) —
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ream, not only 'capture' mode
…iankhou-subprocess-module
mrgrain
approved these changes
Jul 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
No functional changes, adds utilities that need to be wired in.
Unifying how the toolchain talks to the shell (split out of #1758 to keep diffs reviewable).
Add utilities to
packages/@aws-cdk/private-tools/lib/subprocess/index.ts.run(argv)/runSync(argv)— argv-array spawn, never a shell. Windows.cmd/.batshims are resolved by cross-spawn (modern Node refuses to spawn batch shims directly, CVE-2024-27980). Shell injection is impossible by construction, so no argument escaping exists at all. Inside of the trust boundary.runUserCommandLine(line)— the only path to a shell. Reserved for command lines the user authored themselves (cdk.jsonapp,--browser), so it's outside of the trust boundary. Deliberately has no argv form, so command lines cannot be assembled from parts.renderForDisplay()(display-only, allowlist-based quoting),SubprocessErrorwith akinddiscriminant, stateful UTF-8 decoding across pipe chunks, stdin EPIPE tolerance, line-buffered output,capture/inherit-stderr/inheritstdio modes, and opt-out output collection.No call sites change in this PR — the migrations (init, synth, docs, npm, ec2-detection, cdk-assets shell) are in the follow-up PR: #1758.
Adds 56 unit tests.
Checklist
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license