@@ -102,6 +102,39 @@ if (isWindows) {
102
102
t . end ( )
103
103
} )
104
104
105
+ t . test ( 'event with invalid characters runs' , ( t ) => {
106
+ const [ shell , args , opts , cleanup ] = makeSpawnArgs ( {
107
+ event : 'event<:>\x03' , // everything after the word "event" is invalid
108
+ path : 'path' ,
109
+ cmd : 'script "quoted parameter"; second command' ,
110
+ } )
111
+ t . equal ( shell , 'cmd' , 'default shell applies' )
112
+ // disabling no-control-regex because we are testing specifically if the control
113
+ // character gets removed
114
+ // eslint-disable-next-line no-control-regex
115
+ t . match ( args , [ '/d' , '/s' , '/c' , / (?: \\ | \/ ) [ ^ < : > \x03 ] + .c m d \^ " $ / ] , 'got expected args' )
116
+ t . match ( opts , {
117
+ env : {
118
+ npm_package_json : / p a c k a g e \. j s o n $ / ,
119
+ npm_lifecycle_event : 'event' ,
120
+ npm_lifecycle_script : 'script' ,
121
+ npm_config_node_gyp : require . resolve ( 'node-gyp/bin/node-gyp.js' ) ,
122
+ } ,
123
+ stdio : undefined ,
124
+ cwd : 'path' ,
125
+ windowsVerbatimArguments : true ,
126
+ } , 'got expected options' )
127
+
128
+ const filename = unescapeCmd ( args [ args . length - 1 ] )
129
+ const contents = fs . readFileSync ( filename , { encoding : 'utf8' } )
130
+ t . equal ( contents , `@echo off\nscript "quoted parameter"; second command` )
131
+ t . ok ( fs . existsSync ( filename ) , 'script file was written' )
132
+ cleanup ( )
133
+ t . not ( fs . existsSync ( filename ) , 'cleanup removes script file' )
134
+
135
+ t . end ( )
136
+ } )
137
+
105
138
t . test ( 'with a funky ComSpec' , ( t ) => {
106
139
process . env . ComSpec = 'blrorp'
107
140
whichPaths . set ( 'blrorp' , '/bin/blrorp' )
@@ -314,6 +347,38 @@ if (isWindows) {
314
347
t . end ( )
315
348
} )
316
349
350
+ t . test ( 'event with invalid characters runs' , ( t ) => {
351
+ const [ shell , args , opts , cleanup ] = makeSpawnArgs ( {
352
+ event : 'event<:>/\x04' ,
353
+ path : 'path' ,
354
+ cmd : 'script' ,
355
+ args : [ '"quoted parameter";' , 'second command' ] ,
356
+ } )
357
+ t . equal ( shell , 'sh' , 'defaults to sh' )
358
+ // no-control-regex disabled because we're specifically testing control chars
359
+ // eslint-disable-next-line no-control-regex
360
+ t . match ( args , [ '-c' , / (?: \\ | \/ ) [ ^ < : > / \x04 ] + \. s h ' $ / ] , 'got expected args' )
361
+ t . match ( opts , {
362
+ env : {
363
+ npm_package_json : / p a c k a g e \. j s o n $ / ,
364
+ npm_lifecycle_event : 'event' ,
365
+ npm_lifecycle_script : 'script' ,
366
+ } ,
367
+ stdio : undefined ,
368
+ cwd : 'path' ,
369
+ windowsVerbatimArguments : undefined ,
370
+ } , 'got expected options' )
371
+
372
+ const filename = unescapeSh ( args [ args . length - 1 ] )
373
+ const contents = fs . readFileSync ( filename , { encoding : 'utf8' } )
374
+ t . equal ( contents , `#!/usr/bin/env sh\nscript '"quoted parameter";' 'second command'` )
375
+ t . ok ( fs . existsSync ( filename ) , 'script file was written' )
376
+ cleanup ( )
377
+ t . not ( fs . existsSync ( filename ) , 'cleanup removes script file' )
378
+
379
+ t . end ( )
380
+ } )
381
+
317
382
t . test ( 'skips /usr/bin/env if scriptShell is absolute' , ( t ) => {
318
383
const [ shell , args , opts , cleanup ] = makeSpawnArgs ( {
319
384
event : 'event' ,
0 commit comments