Repository navigation
[BUG] npx@8 regression: command injection / impossible to pass a bactick as argument #4873
Description
Is there an existing issue for this?
- I have searched the existing issues
This is a duplicate of #3306, which was closed by mistake.
This issue exists in the latest npm version
- I am using the latest npm
Current Behavior
Let’s say you have a create-blog-post CLI installed globally. You run it like so:
create-blog-post --title 'Cool `ls` tricks'
One day you install create-blog-post locally instead. Then how do you run it? Well, you could just slap npx at the start, right? Wrong! The following does not do what you expect:
npx create-blog-post --title 'Cool `ls` tricks'
Let me show why. I’m using node -p 'process.argv[2]' -- instead of create-blog-post to show that the implementation of that tool wouldn’t matter:
❯ node -p 'process.argv[2]' -- --title 'Cool `ls` tricks'
Cool `ls` tricks
With npx in front:
❯ npx node -p 'process.argv[2]' -- --title 'Cool `ls` tricks'
Cool LICENSE
README.md
lib
map.js
node_modules
package-lock.json
package.json
test tricks
Oops! The argument was treated as shell script, executed ls and put the result in my string (backticks means command interpolation)!
Expected Behavior
npx@6 got it right:
❯ npx --version
6.14.12
❯ npx node -p 'process.argv[2]' -- --title 'Cool `ls` tricks'
Cool `ls` tricks
The worst thing is that I don’t even know how to workaround this issue in npx@8. Trying to add backslashes does not help. I just can’t figure out a way to pass literal backticks as an argument.
Steps To Reproduce
- macOS or Linux (Windows have different issues)
- With this config...
- Run
npx node -p 'process.argv[1]' '`'(tested insh,bash,zsh,fish) - See error:
sh: -c: line 0: unexpected EOF while looking for matching ``'
Environment
- npm: 8.9.0
- Node.js: v18.1.0
- OS Name: Linux
- npm config:
; node bin location = /usr/local/bin/node
; node version = v18.1.0
; npm local prefix = /
; npm version = 8.9.0
; cwd = /
; HOME = /root
; Run `npm config ls -l` to show all defaults.❯ docker run --rm -it node:18 bash
root@a78d74c8a6b5:/# npm i -g npm
changed 15 packages, and audited 202 packages in 6s
11 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
root@a78d74c8a6b5:/# npm -v
8.9.0
root@a78d74c8a6b5:/# node -v
v18.1.0
root@a78d74c8a6b5:/# uname -a
Linux a78d74c8a6b5 5.10.104-linuxkit #1 SMP Wed Mar 9 19:05:23 UTC 2022 x86_64 GNU/Linux
root@a78d74c8a6b5:/# npm config ls
; node bin location = /usr/local/bin/node
; node version = v18.1.0
; npm local prefix = /
; npm version = 8.9.0
; cwd = /
; HOME = /root
; Run `npm config ls -l` to show all defaults.
root@a78d74c8a6b5:/# npx -v
8.9.0
root@a78d74c8a6b5:/# npx node -p 'process.argv[2]' -- --title 'Cool `ls` tricks'
Cool bin
boot
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var tricks
root@a78d74c8a6b5:/# node -p 'process.argv[2]' -- --title 'Cool `ls` tricks'
Cool `ls` tricks
root@a78d74c8a6b5:/#
Activity
nlf commentedon May 9, 2022
thanks for opening a fresh issue! i had it on my todo list for today to reopen the old one but this is great. thanks again
juristr commentedon May 25, 2022
I have a similar, kinda related issue where the
npxcommand would not respect escaping of special symbols, like$for instance.If you have a node script and invoke it like
node myscript --somearg=$foothen$foowould be interpreted as an environment variable. And I can work around this by escaping it likenode myscript --somearg=\$foowhich works just fine.If however I invoke it with
npx node myscript --somearg=\$fooit still gets interpreted as environment variable and the\escape char seems to be ignored which can get annoying if you invoke something likenpx nx generate ... --name=\$fooand it doesn't work.lydell commentedon May 25, 2022
@juristr Good point! That’s another case where using
JSON.stringifyfor escaping args isn’t sufficient.npxreceives--somearg=$fooand escapes that to"--somearg=$foo", but$nameis still expanded inside double quotes.