File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -19,7 +19,9 @@ const run = async ({
1919 // necessary for preventing bash/cmd keywords from overriding
2020 if ( ! isWindowsShell ) {
2121 if ( args . length > 0 ) {
22- args [ 0 ] = '"' + args [ 0 ] + '"'
22+ // single-quote so shell metacharacters in the executable name are taken
23+ // literally; double quotes still expand $(), backticks, $var and "
24+ args [ 0 ] = `'${ args [ 0 ] . replace ( / ' / g, `'\\''` ) } '`
2325 }
2426 }
2527
Original file line number Diff line number Diff line change @@ -130,6 +130,20 @@ t.test('isWindows', async t => {
130130 await runScript ( )
131131} )
132132
133+ t . test ( 'escapes executable name to neutralize shell metacharacters' , async t => {
134+ let pkg
135+ const { runScript } = await mockRunScript ( t , {
136+ 'ci-info' : { isCI : true } ,
137+ '@npmcli/run-script' : async ( opts ) => {
138+ pkg = opts . pkg
139+ } ,
140+ '../lib/is-windows.js' : false ,
141+ } )
142+
143+ await runScript ( { args : [ `evil'; touch pwned #` ] } )
144+ t . equal ( pkg . scripts . npx , `'evil'\\''; touch pwned #'` )
145+ } )
146+
133147t . test ( 'isNotWindows' , async t => {
134148 const { runScript } = await mockRunScript ( t , {
135149 'ci-info' : { isCI : true } ,
You can’t perform that action at this time.
0 commit comments