Skip to content
AX Principles
AX-SYS-26Intermediate

Never interpolate agent input into commands or queries

Nunca interpoles la entrada del agente en comandos o consultas

#all-industries#mcp

Treat every argument an agent sends as untrusted input, and pass it to shells, databases and interpreters only as parameters, never as part of a string you build and execute.

Why

A tool's arguments are written by a model, and the model's context can contain text an attacker planted in a web page, an email or a document. Whatever reaches your tool may therefore be hostile even when the agent and its user are not. OWASP lists command injection as MCP05 in its MCP Top 10: it happens when an agent's request turns into a system command, script, query or code snippet built from untrusted input without validation. The defenses are old and well understood, and they apply unchanged. OWASP's guidance is to never use shell=True, eval(), exec() or string-built commands, to execute with structured parameters, to validate agent output against a schema before acting on it, and to use parameterized SQL and APIs. Its command injection cheat sheet puts avoiding OS commands first (a library call cannot be talked into doing something else) and parameterization plus input validation second. The MCP specification makes the server's side explicit: servers MUST validate all tool inputs and sanitize tool outputs. Your tool's input schema is the first gate; parameterized execution is the one that holds when the schema allows a string.

Do

Validate arguments against the tool's schema and pass them to commands and queries as separate parameters.

Don't

Build a shell command, SQL statement or eval string by concatenating what the agent sent.

Artifact

# Bad: the agent's path becomes part of the command line
os.system(f"tar -czf backup.tgz {args['path']}")
cursor.execute(f"SELECT * FROM orders WHERE customer = '{args['customer']}'")

# Good: arguments stay data
subprocess.run(["tar", "-czf", "backup.tgz", "--", args["path"]], check=True)
cursor.execute("SELECT * FROM orders WHERE customer = %s", (args["customer"],))

Citations

  1. [01]
    MCP Specification 2026-07-28: Tools (Security Considerations) ↗

    Servers MUST validate all tool inputs, implement proper access controls, rate limit tool invocations, and sanitize tool outputs

  2. [02]
    OWASP MCP Top 10 (MCP05:2025 Command Injection & Execution) ↗

    Command injection occurs when an AI agent constructs and executes system commands, shell scripts, API calls, or code snippets using untrusted input without proper validation or sanitization. Never use shell=True, eval(), exec(), or string-built commands; always execute with structured parameters, validate agent output against schemas before execution, and use parameterized SQL/APIs, never interpolating input

  3. [03]
    OWASP Cheat Sheet Series: OS Command Injection Defense ↗

    The primary defense is to avoid calling OS commands directly, since built-in library functions cannot be manipulated to perform other tasks; where that is not possible, use parameterization, structured mechanisms that automatically enforce the separation between data and command, together with input validation