@@ -259,6 +259,90 @@ export const validateEnvironmentVariables = (env: Record<string, any>): void =>
259259 }
260260}
261261
262+ /**
263+ * Validates that command arguments don't contain flags that enable arbitrary code execution
264+ * This prevents attacks where whitelisted commands are used with dangerous flags
265+ * (e.g., "npx -c malicious-command" or "python -c malicious-code")
266+ * @param command The command to validate
267+ * @param args The arguments to validate
268+ */
269+ export const validateCommandFlags = ( command : string , args : string [ ] ) : void => {
270+ // Define dangerous flags for each command that enable code execution
271+ const dangerousFlagsByCommand : Record < string , string [ ] > = {
272+ npx : [
273+ '-c' , // Execute shell commands
274+ '--call' , // Execute shell commands
275+ '--shell-auto-fallback' , // Shell execution fallback
276+ '-y' // Auto-confirms installation prompts
277+ ] ,
278+ node : [
279+ '-e' , // Execute JavaScript code
280+ '--eval' , // Execute JavaScript code
281+ '-p' , // Evaluate and print JavaScript code
282+ '--print' , // Evaluate and print JavaScript code
283+ '--inspect' , // Enable remote debugging (security risk)
284+ '--inspect-brk' , // Enable remote debugging with breakpoint (security risk)
285+ '--experimental-policy' // Could load malicious policies
286+ ] ,
287+ python : [
288+ '-c' , // Execute Python code
289+ '-m' // Run library modules (could run malicious modules)
290+ ] ,
291+ python3 : [
292+ '-c' , // Execute Python code
293+ '-m' // Run library modules (could run malicious modules)
294+ ] ,
295+ docker : [
296+ 'run' , // Run containers (too powerful)
297+ 'exec' , // Execute in containers
298+ '-v' , // Mount host filesystems
299+ '--volume' , // Mount host filesystems
300+ '--privileged' , // Privileged mode
301+ '--cap-add' , // Add capabilities
302+ '--security-opt' , // Modify security options
303+ '--network' , // Host network access (catches --network=host and --network host)
304+ '--pid' , // Host PID namespace (catches --pid=host and --pid host)
305+ '--ipc' // Host IPC namespace (catches --ipc=host and --ipc host)
306+ ]
307+ }
308+
309+ const dangerousFlags = dangerousFlagsByCommand [ command ] || [ ]
310+
311+ // Collect single-char dangerous flags (e.g. '-c' -> 'c') for combined flag detection
312+ const dangerousShortChars = new Set ( dangerousFlags . filter ( ( f ) => / ^ - [ a - z A - Z ] $ / . test ( f ) ) . map ( ( f ) => f [ 1 ] . toLowerCase ( ) ) )
313+
314+ for ( const arg of args ) {
315+ if ( typeof arg !== 'string' ) continue
316+
317+ const normalizedArg = arg . toLowerCase ( ) . trim ( )
318+
319+ // Check for dangerous flags in various forms (exact, =value, space-separated value)
320+ for ( const flag of dangerousFlags ) {
321+ const lowerCaseFlag = flag . toLowerCase ( )
322+ if ( normalizedArg === lowerCaseFlag ) {
323+ throw new Error ( `Argument '${ arg } ' is not allowed for command '${ command } '.` )
324+ }
325+ if ( normalizedArg . startsWith ( lowerCaseFlag + '=' ) ) {
326+ throw new Error ( `Argument '${ arg } ' contains flag '${ flag } ' that is not allowed for command '${ command } '.` )
327+ }
328+ if ( flag . startsWith ( '-' ) && normalizedArg . startsWith ( lowerCaseFlag + ' ' ) ) {
329+ throw new Error ( `Argument '${ arg } ' contains flag '${ flag } ' that is not allowed for command '${ command } '.` )
330+ }
331+ }
332+
333+ // Check for combined short flags (e.g. "-yc" = "-y" + "-c")
334+ // A combined flag starts with a single '-', is not a long flag '--', and has multiple characters after '-'
335+ if ( / ^ - [ a - z A - Z ] { 2 , } / . test ( normalizedArg ) ) {
336+ const flagChars = normalizedArg . slice ( 1 ) // strip leading '-'
337+ for ( const ch of flagChars ) {
338+ if ( dangerousShortChars . has ( ch ) ) {
339+ throw new Error ( `Argument '${ arg } ' contains dangerous flag '-${ ch } ' for command '${ command } '.` )
340+ }
341+ }
342+ }
343+ }
344+ }
345+
262346export const validateMCPServerConfig = ( serverParams : any ) : void => {
263347 // Validate the entire server configuration
264348 if ( ! serverParams || typeof serverParams !== 'object' ) {
@@ -276,6 +360,11 @@ export const validateMCPServerConfig = (serverParams: any): void => {
276360 if ( serverParams . args && Array . isArray ( serverParams . args ) ) {
277361 validateArgsForLocalFileAccess ( serverParams . args )
278362 validateCommandInjection ( serverParams . args )
363+
364+ // Validate command-specific dangerous flags
365+ if ( serverParams . command ) {
366+ validateCommandFlags ( serverParams . command , serverParams . args )
367+ }
279368 }
280369
281370 // Validate environment variables
0 commit comments