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

Quote editor.path argument #112

Closed
wants to merge 1 commit into from
Closed

Quote editor.path argument #112

wants to merge 1 commit into from

Conversation

rekmarks
Copy link
Member

The editor.path string can contain spaces, e.g. /Applications/Visual Studio Code.app/.... This string is passed to execa(), which attempts to execute it as a command in the user's shell. On some systems, this string must be quoted, or else the shell will interpret the substring until the first space as the command, and either error or execute the wrong thing.

The `editor.path` string can contain spaces, e.g. `/Applications/Visual Studio Code.app/...`. This string is passed to `execa()`, which attempts to execute it as a command in the user's shell. On some systems, this string must be quoted, or else the shell will interpret the substring until the first space as the command, and either error or execute the wrong thing.
@rekmarks rekmarks requested a review from a team as a code owner November 30, 2023 03:14
@rekmarks rekmarks marked this pull request as draft November 30, 2023 04:06
Copy link
Contributor

@legobeat legobeat left a comment

Choose a reason for hiding this comment

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

From https://github.com/sindresorhus/execa/tree/v5.1.1#execacommandcommand-options:

If the file or an argument contains spaces, they must be escaped with backslashes. This matters especially if command is not a constant but a variable, for example with __dirname or process.cwd(). Except for spaces, no escaping/quoting is needed.

https://github.com/MetaMask/create-release-branch/actions/runs/7041542167/job/19164270553

@rekmarks
Copy link
Member Author

@legobeat hmm, that's interesting. The weirdness here is that this has not been a problem for anyone who has used this tool, except myself as described above. Specifically, the error I got was:

/bin/sh: /Applications/Visual: No such file or directory
ErrorWithCause: Encountered an error while waiting for the release spec to be edited.
    at wrapError (.../node_modules/@metamask/create-release-branch/dist/misc-utils.js:86:23)
    at waitForUserToEditReleaseSpecification (.../node_modules/@metamask/create-release-branch/dist/release-specification.js:93:42)
...

I already tried my change locally and it fixes the error. However, according to this source, we should probably single-quote paths:

If you want to work with files with spaces or special characters in the filename, you may have to use quotes. For instance, if you wanted to create a file with a space in the name, you could use the following:
% cp /dev/null 'a file with spaces in the name'

I'm discussing with @mcmire where we're going to introduce quoting / escaping. I'm leaving this in draft until it's ready for another round of reviews.

@legobeat
Copy link
Contributor

legobeat commented Nov 30, 2023

@legobeat hmm, that's interesting. The weirdness here is that this has not been a problem for anyone who has used this tool, except myself as described above. Specifically, the error I got was:

/bin/sh: /Applications/Visual: No such file or directory
ErrorWithCause: Encountered an error while waiting for the release spec to be edited.
    at wrapError (.../node_modules/@metamask/create-release-branch/dist/misc-utils.js:86:23)
    at waitForUserToEditReleaseSpecification (.../node_modules/@metamask/create-release-branch/dist/release-specification.js:93:42)
...

I already tried my change locally and it fixes the error. However, according to this source, we should probably single-quote paths:

If you want to work with files with spaces or special characters in the filename, you may have to use quotes. For instance, if you wanted to create a file with a space in the name, you could use the following:
% cp /dev/null 'a file with spaces in the name'

I'm discussing with @mcmire where we're going to introduce quoting / escaping. I'm leaving this in draft until it's ready for another round of reviews.

I'd wager that either quoting with single-quote or shell-escaping (with caveats - beware of shell-injection here) will work for arguments while escaping should be correct for the command itself?

@rekmarks
Copy link
Member Author

@legobeat, single-quoting seems to work fine on my system:

/bin/zsh:

'echo' 'foo'
foo

/bin/sh:

'echo' 'foo'
foo

And this would be consistent with this source:

Single quotes: '...' removes the special meaning of every character between the quotes. Everything inside single quotes becomes a literal string. The only character that you can't safely enclose in single quotes is a single quote.

@legobeat
Copy link
Contributor

@legobeat, single-quoting seems to work fine on my system:

/bin/zsh:

'echo' 'foo'
foo

/bin/sh:

'echo' 'foo'
foo

And this would be consistent with this source:

Single quotes: '...' removes the special meaning of every character between the quotes. Everything inside single quotes becomes a literal string. The only character that you can't safely enclose in single quotes is a single quote.

Why not support single-quotes?

@cryptodev-2s
Copy link
Contributor

cryptodev-2s commented Nov 30, 2023

@legobeat @rekmarks we currently use execa 5.1.1 and on the recent version 8+ they have introduced the escaping Arguments are [automatically escaped](https://www.npmjs.com/package/execa#shell-syntax). They can contain any character, including spaces. This is the preferred method when executing single commands.
https://www.npmjs.com/package/execa
@mcmire we can consider upgrading the package

@legobeat
Copy link
Contributor

legobeat commented Nov 30, 2023

@legobeat @rekmarks we currently use execa 5.1.1 and on the recent version 8+ they have introduced the escaping Arguments are [automatically escaped](https://www.npmjs.com/package/execa#shell-syntax). They can contain any character, including spaces. This is the preferred method when executing single commands. https://www.npmjs.com/package/execa we can consider upgrading the package

Just heads up that execa is ESM-only starting with v6.0.0, so this package would have to be migrated to ESM before upgrading that dependency further.
https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c

EDIT: Looks like it would actually be reasonable to stay on CommonJS and utilize dynamic imports. The mocking and spying in the tests would need to be rewritten somewhat to accommodate (or does Jest support running the tests as ESM while the package is otherwise CommonJS? 🤔 )

@rekmarks
Copy link
Member Author

rekmarks commented Dec 8, 2023

Closing in favor of #121.

@rekmarks rekmarks closed this Dec 8, 2023
@rekmarks rekmarks mentioned this pull request Dec 8, 2023
rekmarks added a commit that referenced this pull request Dec 8, 2023
This PR updates `execa` to `^8.0.1`. Since `execa@>=6.0.0` is ESM-only and `jest` only has experimental ESM support (jestjs/jest#10976), this required switching from `ts-jest` to `babel-jest`. To minimize dependency transpilation, the ESM packages that are necessary to transpile are enumerated in `jest.config.js`.

This version of `execa` includes [automatic escaping of shell arguments](https://github.com/sindresorhus/execa/tree/v8.0.1#execafile-arguments-options), which was the entire point of #112, #113, and this PR.

The state of ESM support in the Node.js ecosystem is absolutely horrible, and I would not recommend further migrations for the time being. We should continue to dual-release our packages and avoid ESM-only dependencies until the ecosystem has matured. For details see the above `jest` issue and nodejs/node#37648.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants