All rules MCP05

MCP05 — Tool Input Injection

critical active

Summary

Tool input parameters flow into child_process exec/spawn or filesystem paths without sanitisation.

Detection

AST taint trace from tool handler parameters to child_process.exec/spawn/execSync/spawnSync and unsanitised fs.* path arguments, with bounded same-file inter-procedural traversal through local helper functions. Conservative limits apply (depth cap; ambiguous same-name helpers are skipped).

Bad example

// BAD — input concatenated into a shell command
server.tool('run', async ({ cmd }) => exec(`ls ${cmd}`));

Good example

// GOOD — execFile with array args, no shell
server.tool('run', async ({ cmd }) => {
    if (!/^[a-z0-9-]+$/.test(cmd)) throw new Error('invalid');
    await execFile('ls', [cmd], { shell: false, timeout: 5_000 });
});

Fix

Replace exec with execFile/spawn (shell: false). Validate every input through a strict allow-list before it reaches a syscall.

References