Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

child_process: escape args[] for shell #29576

Closed
wants to merge 21 commits into from

Conversation

Artoria2e5
Copy link

@Artoria2e5 Artoria2e5 commented Sep 16, 2019

Closes #29532

(NO LONGER) BREAKING CHANGE: This changes the behavior of args[] in shell: true to
escape globs and other metacharacters. If you want to keep your scripts,
do it the proper way and stuff them in "command."

Checklist
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

@nodejs-github-bot nodejs-github-bot added the child_process Issues and PRs related to the child_process subsystem. label Sep 16, 2019
@Artoria2e5
Copy link
Author

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.

@Artoria2e5
Copy link
Author

Artoria2e5 commented Sep 16, 2019

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

@Artoria2e5
Copy link
Author

Artoria2e5 commented Sep 17, 2019

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');

@Artoria2e5 Artoria2e5 marked this pull request as ready for review September 17, 2019 09:59
@Artoria2e5
Copy link
Author

Artoria2e5 commented Sep 17, 2019

The test is almost passing on Windows. What fails include:

  • That powershell test. The builtin Write-Line works but external commands like bash still fail with some characters (leading space, newline) being swallowed as well as quote alternations. Gotta dig into the PS source code to see what it is doing to call that command.
    + `Lorem Ipsu\\"m dolor sit on $'\\\\a\\a' ringing chair. `
    - `$'  Lorem  Ipsu""m\\ndolor\\tsit' $'on \\\\a\\a ringing chair.' `
    • So PS does it via System.Management.Automation.NativeCommandProcessor, which gets the stringified arguments for System.Diagnostics.ProcessStartInfo from NativeCommandParameterBinder.BindParameters. That part, however, isn't something I can read at midnight...
    • I should probably first port it to the same node-based check cmd uses to get a more representative sample...

Ho boy how did the one infalliable thing fail

Artoria2e5 and others added 17 commits January 11, 2021 18:55
node-cross-spawn points me to a page with a not entirely correct Perl
thing for escaping cmd arguments. Throwing its metacharacters in does
improve our coverage of cmd cases. It also lead me to the unfortunate
conclusion that I have to use an undocumented trivia to make quotes work
consistently on CMD.

Applied the working change about sh env/command stuff.
(NOT INCLUDING THE ARRAY STUFF)

Co-authored-by: Antoine du Hamel <[email protected]>
Is there a way to automatically do this? Running lint-md -o rewrites too much.
lib/child_process.js Outdated Show resolved Hide resolved
Comment on lines +582 to +585
if (!options.shellEscape)
quote = (s) => s;
else if (typeof options.shellEscape == 'function')
quote = options.shellEscape;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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;
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the ERR_INVALID_ARG_TYPE throw earliser would've caught that. When was validateCallback even introduced?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the ERR_INVALID_ARG_TYPE throw earliser would've caught that.

Yes you're probably right. Could add a test case for this scenario please?

lib/child_process.js Outdated Show resolved Hide resolved
lib/child_process.js Outdated Show resolved Hide resolved
@bnb
Copy link
Contributor

bnb commented Jan 11, 2022

@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 👍🏻

@cjihrig
Copy link
Contributor

cjihrig commented Feb 21, 2023

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.

@cjihrig cjihrig closed this Feb 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
child_process Issues and PRs related to the child_process subsystem. review wanted PRs that need reviews. semver-minor PRs that contain new features and should be released in the next minor version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

child_process should individually escape args[] on shell: true