Repository navigation
child_process: escape args[] for shell - #29576
Artoria2e5 wants to merge 21 commits into
Conversation
|
Going to wait for the tests to weed out some extra tests I need to change. The removal of cmd → vwa might mess up a few. |
c9f2377 to
48decad
Compare
48decad to
a981fe7
Compare
a981fe7 to
8edd7de
Compare
|
The documentation does feel a little repetitive at times with multiple segments used to describe the exact same type of spawn normalisation. I am thinking about collapsing them down into the same place and linking the others in, but should that be moved to a different PR? CC @bnoordhuis |
8edd7de to
36d156e
Compare
36d156e to
4182664
Compare
4182664 to
36b01c4
Compare
|
Windows is a fustercluck for those familiar with Unix cmdline handling. The bash tests should pass, but I am gonna see how they fail on my own copy of Windows and lower the bars on cmd accordingly... The vcbuild thing looks painful. But it does look like I can go around the native require with a bit of: const current_cp = require('child_process')
function spawnSync(file, args, options) {
options = normalizeSpawnArguments(file, args, options);
console.log(options.args);
return current_cp.spawnSync(options.file, options.args.slice(1), options);
}
// normalizeSpawnArguments:
return { /* ... */ shell: false }
// ...
const _forkChild = current_cp._forkChild
module.exports = { _forkChild, ...current_cp, spawnSync }const cp = require('../../../patch_cp.js'); |
36b01c4 to
ef200d9
Compare
ef200d9 to
7377359
Compare
|
The test is almost passing on Windows. What fails include:
Ho boy how did the one infalliable thing fail |
7377359 to
d8745e4
Compare
d8745e4 to
6d28689
Compare
6d28689 to
4d915b5
Compare
(NOT INCLUDING THE ARRAY STUFF) Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
Is there a way to automatically do this? Running lint-md -o rewrites too much.
28915e5 to
46d190b
Compare
| if (!options.shellEscape) | ||
| quote = (s) => s; | ||
| else if (typeof options.shellEscape == 'function') | ||
| quote = options.shellEscape; |
There was a problem hiding this comment.
What if options.shellEscape is truthy but not a function (E.G. 1)? I think we should throw a ERR_INVALID_CALLBACK error in that case.
| if (!options.shellEscape) | |
| quote = (s) => s; | |
| else if (typeof options.shellEscape == 'function') | |
| quote = options.shellEscape; | |
| if (options.shellEscape === false || options.shellEscape === undefined) { | |
| quote = (s) => s; | |
| } else if (options.shellEscape !== true) { | |
| validateCallback(options.shellEscape); | |
| quote = options.shellEscape; | |
| } |
There was a problem hiding this comment.
I thought the ERR_INVALID_ARG_TYPE throw earliser would've caught that. When was validateCallback even introduced?
There was a problem hiding this comment.
I thought the
ERR_INVALID_ARG_TYPEthrow earliser would've caught that.
Yes you're probably right. Could add a test case for this scenario please?
Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
|
@Artoria2e5 is this roughly ready? Looks like there's a conflict and one remaining piece of feedback. Would love to get this merged (if possible!). If not, no worries - we can close it out 👍🏻 |
|
The last comment on this PR was over a year ago, and suggested we could close this... so I'm closing. Feel free to revisit though. |
- combine COMMAND and ARGS when invoking spawn() with shell:true
- suppress runtime deprecation warnings while preserving current semantics
## [why]
NodeJS introduced deprecation DEP0190 for spawn(), documented in NodeJS-v23.11.0.
In NodeJS-v24.0.0+, it emits runtime warnings. The deprecation targets the pattern
`spawn(COMMAND, ARGS, { shell: true })`, which does not escape ARGS and instead
joins them to COMMAND with simple space separation (e.g., `[COMMAND, ...ARGS].join(' ')`).
While this behavior presents a security risk (command injection) if inputs are not
properly sanitized, there is currently (as of 2026-04-19; NodeJS-v25) no drop-in
replacement. The alternative `exec()` is not suitable, as it does not support
required stdio customization.
Refs:
- [NodeJS ~ Deprecated APIs/DEP0190](https://nodejs.org/download/release/latest-jod/docs/api/deprecations.html#DEP0190)
- [GH/nodejs/node ~ DEP0190 discussion](nodejs/node#58763 (comment))
- [GH/nodejs/node ~ bug: child_process, args should be escaped](nodejs/node#29532)
- [GH/nodejs/node ~ PR/failed: child_process - escape args for shell:true](nodejs/node#29576)
- combine COMMAND and ARGS when invoking spawn() with shell:true
- suppress runtime deprecation warnings while preserving current semantics
## [why]
NodeJS introduced deprecation DEP0190 for spawn(), documented in NodeJS-v23.11.0.
In NodeJS-v24.0.0+, it emits runtime warnings. The deprecation targets the pattern
`spawn(COMMAND, ARGS, { shell: true })`, which does not escape ARGS and instead
joins them to COMMAND with simple space separation (e.g., `[COMMAND, ...ARGS].join(' ')`).
While this behavior presents a security risk (command injection) if inputs are not
properly sanitized, there is currently (as of 2026-04-19; NodeJS-v25) no drop-in
replacement. The alternative `exec()` is not suitable, as it does not support
required stdio customization.
### Refs
- [NodeJS ~ Deprecated APIs/DEP0190](https://nodejs.org/download/release/latest-jod/docs/api/deprecations.html#DEP0190)
- [GH/nodejs/node ~ DEP0190 discussion](nodejs/node#58763 (comment))
- [GH/nodejs/node ~ bug: child_process, args should be escaped](nodejs/node#29532)
- [GH/nodejs/node ~ PR/failed: child_process - escape args for shell:true](nodejs/node#29576)
- combine COMMAND and ARGS when invoking spawn() with shell:true
- suppress runtime deprecation warnings while preserving current semantics
## [why]
NodeJS introduced deprecation DEP0190 for spawn(), documented in NodeJS-v23.11.0.
In NodeJS-v24.0.0+, it emits runtime warnings. The deprecation targets the pattern
`spawn(COMMAND, ARGS, { shell: true })`, which does not escape ARGS and instead
joins them to COMMAND with simple space separation (e.g., `[COMMAND, ...ARGS].join(' ')`).
While this behavior presents a security risk (command injection) if inputs are not
properly sanitized, there is currently (as of 2026-04-19; NodeJS-v25) no drop-in
replacement. The alternative `exec()` is not suitable, as it does not support
required stdio customization.
### Refs
- [NodeJS ~ Deprecated APIs/DEP0190](https://nodejs.org/download/release/latest-jod/docs/api/deprecations.html#DEP0190)
- [GH/nodejs/node ~ DEP0190 discussion](nodejs/node#58763 (comment))
- [GH/nodejs/node ~ bug: child_process, args should be escaped](nodejs/node#29532)
- [GH/nodejs/node ~ PR/failed: child_process - escape args for shell:true](nodejs/node#29576)
Closes #29532
(NO LONGER) BREAKING CHANGE: This changes the behavior of args[] in
shell: truetoescape globs and other metacharacters. If you want to keep your scripts,
do it the proper way and stuff them in "command."
Checklist