@@ -22,10 +22,28 @@ const getExecutionShell = async (): Promise<undefined | string> => {
22
22
}
23
23
} ;
24
24
25
+ const bashSpecialCharacters = / [ & | < > \s ] / g;
26
+ // escape whitespace & special characters in an argument when not quoted
27
+ const shouldEscapeArg = ( arg : string ) => {
28
+ const hasSpecialCharacter = bashSpecialCharacters . test ( arg ) ;
29
+ const isSingleCharacter = arg . length === 1 ;
30
+ const isQuoted = ( arg . startsWith ( `"` ) && arg . endsWith ( `"` ) ) || ( arg . startsWith ( `'` ) && arg . endsWith ( `'` ) ) ;
31
+ return hasSpecialCharacter && ! isSingleCharacter && ! isQuoted ;
32
+ } ;
33
+
34
+ /* based on libuv process.c used by nodejs, only quotes are escaped for shells. if using git bash need to escape whitespace & special characters in an argument */
35
+ const escapeArgs = ( shell : string | undefined , args : string [ ] ) => {
36
+ // only escape args for git bash
37
+ if ( process . platform !== "win32" || shell == undefined ) return args ;
38
+ return args . map ( ( arg ) => ( shouldEscapeArg ( arg ) ? `"${ arg . replaceAll ( '"' , '\\"' ) } "` : arg ) ) ;
39
+ } ;
40
+
25
41
export const buildExecuteShellCommand =
26
42
async ( timeout : number ) : Promise < Fig . ExecuteCommandFunction > =>
27
43
async ( { command, env, args, cwd } : Fig . ExecuteCommandInput ) : Promise < Fig . ExecuteCommandOutput > => {
28
- const child = spawn ( command , args , { cwd, env : { ...process . env , ...env , ISTERM : "1" } , shell : await getExecutionShell ( ) } ) ;
44
+ const executionShell = await getExecutionShell ( ) ;
45
+ const escapedArgs = escapeArgs ( executionShell , args ) ;
46
+ const child = spawn ( command , escapedArgs , { cwd, env : { ...process . env , ...env , ISTERM : "1" } , shell : executionShell } ) ;
29
47
setTimeout ( ( ) => child . kill ( "SIGKILL" ) , timeout ) ;
30
48
let stdout = "" ;
31
49
let stderr = "" ;
0 commit comments