(command: string, args: string[])
| 315 | * @param args The arguments to validate |
| 316 | */ |
| 317 | export const validateCommandFlags = (command: string, args: string[]): void => { |
| 318 | // Define dangerous flags for each command that enable code execution |
| 319 | const dangerousFlagsByCommand: Record<string, string[]> = { |
| 320 | npx: [ |
| 321 | '-c', // Execute shell commands |
| 322 | '--call', // Execute shell commands |
| 323 | '--shell-auto-fallback', // Shell execution fallback |
| 324 | '-y', // Auto-confirms installation prompts |
| 325 | '--yes', // Auto-confirms installation prompts |
| 326 | '--node-options' // Passes arbitrary Node flags to underlying process, bypassing node flag blocklist |
| 327 | ], |
| 328 | node: [ |
| 329 | '-e', // Execute JavaScript code |
| 330 | '--eval', // Execute JavaScript code |
| 331 | '-p', // Evaluate and print JavaScript code |
| 332 | '--print', // Evaluate and print JavaScript code |
| 333 | '--inspect', // Enable remote debugging (security risk) |
| 334 | '--inspect-brk', // Enable remote debugging with breakpoint (security risk) |
| 335 | '--experimental-policy', // Could load malicious policies |
| 336 | '-r', // Short alias for --require |
| 337 | '--require', // Preload a CommonJS module before script runs |
| 338 | '--loader', // Custom ES module loader hook (code execution) |
| 339 | '--experimental-loader', // Same as --loader, older Node alias |
| 340 | '--import', // Preload ESM module before entry script (Node 18+) |
| 341 | '--env-file' // Read env vars from a local file (Node 20+, local file access) |
| 342 | ], |
| 343 | python: [ |
| 344 | '-c', // Execute Python code |
| 345 | '-m' // Run library modules (could run malicious modules) |
| 346 | ], |
| 347 | python3: [ |
| 348 | '-c', // Execute Python code |
| 349 | '-m' // Run library modules (could run malicious modules) |
| 350 | ], |
| 351 | docker: [ |
| 352 | 'run', // Run containers (too powerful) |
| 353 | 'build', // Pulls a container and executes the run instructions |
| 354 | 'exec', // Execute in containers |
| 355 | 'compose', // Subcommand that starts containers (same risk as run) |
| 356 | '-v', // Mount host filesystems |
| 357 | '--volume', // Mount host filesystems |
| 358 | '--mount', // Alternative to -v/--volume for mounting host paths |
| 359 | '--volumes-from', // Mount volumes from another container (filesystem access) |
| 360 | '--privileged', // Privileged mode |
| 361 | '--cap-add', // Add capabilities |
| 362 | '--security-opt', // Modify security options |
| 363 | '--device', // Add host device files to container (privilege escalation) |
| 364 | '--entrypoint', // Override container entrypoint (arbitrary code execution) |
| 365 | '--network', // Host network access (catches --network=host and --network host) |
| 366 | '--pid', // Host PID namespace (catches --pid=host and --pid host) |
| 367 | '--ipc', // Host IPC namespace (catches --ipc=host and --ipc host) |
| 368 | '--env-file' // Read env vars from a local host file (local file access) |
| 369 | ] |
| 370 | } |
| 371 | |
| 372 | const dangerousFlags = dangerousFlagsByCommand[command] || [] |
| 373 | |
| 374 | // Collect single-char dangerous flags (e.g. '-c' -> 'c') for combined flag detection |
no test coverage detected