@@ -28,6 +28,12 @@ const DANGEROUS_FLAGS = new Set([
2828 '--require' , '-r'
2929] ) ;
3030
31+ /**
32+ * Defense-in-depth: Shell metacharacters that could enable command injection
33+ * when shell: true is used on Windows
34+ */
35+ const SHELL_METACHARACTERS = [ '&' , '|' , '>' , '<' , '^' , '%' , ';' , '$' , '`' , '\n' , '\r' ] ;
36+
3137/**
3238 * Validate that a command is in the safe allowlist
3339 */
@@ -39,11 +45,22 @@ function isCommandSafe(command: string | undefined): boolean {
3945}
4046
4147/**
42- * Validate that args don't contain dangerous interpreter flags
48+ * Validate that args don't contain dangerous interpreter flags or shell metacharacters
4349 */
4450function areArgsSafe ( args : string [ ] | undefined ) : boolean {
4551 if ( ! args || args . length === 0 ) return true ;
46- return ! args . some ( arg => DANGEROUS_FLAGS . has ( arg ) ) ;
52+
53+ // Check for dangerous interpreter flags
54+ if ( args . some ( arg => DANGEROUS_FLAGS . has ( arg ) ) ) return false ;
55+
56+ // On Windows with shell: true, check for shell metacharacters that could enable injection
57+ if ( process . platform === 'win32' ) {
58+ if ( args . some ( arg => SHELL_METACHARACTERS . some ( char => arg . includes ( char ) ) ) ) {
59+ return false ;
60+ }
61+ }
62+
63+ return true ;
4764}
4865
4966/**
@@ -171,7 +188,7 @@ async function checkCommandHealth(server: CustomMcpServer, startTime: number): P
171188 return resolve ( {
172189 serverId : server . id ,
173190 status : 'unhealthy' ,
174- message : 'Args contain dangerous interpreter flags' ,
191+ message : 'Args contain dangerous flags or shell metacharacters ' ,
175192 checkedAt : new Date ( ) . toISOString ( ) ,
176193 } ) ;
177194 }
@@ -394,14 +411,17 @@ async function testCommandConnection(server: CustomMcpServer, startTime: number)
394411 return resolve ( {
395412 serverId : server . id ,
396413 success : false ,
397- message : 'Args contain dangerous interpreter flags' ,
414+ message : 'Args contain dangerous flags or shell metacharacters ' ,
398415 } ) ;
399416 }
400417
401418 const args = server . args || [ ] ;
419+
420+ // On Windows, use shell: true to properly handle .cmd/.bat scripts like npx
402421 const proc = spawn ( server . command ! , args , {
403422 stdio : [ 'pipe' , 'pipe' , 'pipe' ] ,
404423 timeout : 15000 , // OS-level timeout for reliable process termination
424+ shell : process . platform === 'win32' , // Required for Windows to run npx.cmd
405425 } ) ;
406426
407427 let stdout = '' ;
0 commit comments