Command injection in an MCP server happens when a tool passes text it received, from the model or a user, into a system shell. The attacker's text becomes commands that run with the server's privileges. Prevent it by never building shell strings from input, using argument arrays, validating values and running servers with minimal rights.
What is command injection?
OWASP defines command injection as an attack whose goal is execution of arbitrary commands on the host operating system via a vulnerable application. It is possible when an application passes unsafe user supplied data to a system shell, and the commands usually run with the privileges of the vulnerable application. OWASP attributes it largely to insufficient input validation.
Nothing about that is new. What is new is who supplies the input.
Why are MCP servers a fresh target?
An MCP server exposes tools to an AI client. A tool such as "convert file" or "run query" often wraps a command line program. The caller is a language model, which builds the arguments from conversation, from documents it read, and from tool results.
That means the string reaching your tool may be influenced by untrusted text, for example a web page the model summarised earlier. The server author cannot assume the arguments came from a trusted human.
The MCP project's security guidance page discusses local servers specifically. It says local servers may have direct access to the user's system, and without sandboxing and consent, risks include arbitrary code execution with the client's privileges, no visibility into what commands run, and data loss. It also lists malicious startup commands in client configuration as an attack path.
What does the vulnerable pattern look like?
In words, to avoid publishing anything usable: a tool receives a filename from its caller, builds a command line by joining a fixed program name and that filename into one string, and hands the string to a shell. If the filename contains shell control characters, the shell treats part of it as a second command.
The weakness is the join. It turns data into code.
How do you prevent it?
Avoid the shell. Call programs with an argument list, so the operating system receives each argument separately and no shell interprets it. Most languages have an API for this.
Prefer libraries over command line tools. If a native library does the job, use it and skip the process entirely.
Validate against an allowlist. Constrain arguments to expected shapes: a filename from a known directory, a number in a range, a choice from a fixed list. Reject, do not clean.
Contain the process. Run the server as a low privilege user, in a container or sandbox, with only the directories and network access it needs.
Limit what the tool can do. A tool that can only read one folder is a smaller target than one that runs anything.
Show the user what runs. For tools with side effects, require confirmation with the real command visible.
What does a constructed review look like?
A team audits its internal MCP server with eight tools. They search the code for process-launching calls and find three. Two already use argument arrays. One builds a string for a shell because it needs a pipe. They replace the pipe with two calls and a small in-process step, restrict the path argument to a single directory, and move the server into a container with a read-only mount. Then they write a test that sends awkward inputs, such as spaces and quote characters, and asserts that the tool treats them as a single value.
How to check or apply this
- Search the server code for every place that starts a process or uses a shell.
- Replace string-built commands with argument arrays, or with a library call.
- Add allowlist validation for each parameter, with a test per rule.
- Run the server with the least privilege and no ambient credentials.
- Log each tool call with its arguments, and review unusual ones.
- Put a policy layer between agents and servers so tool calls are checked before they run.
Safeguard's MCP Guardrail applies policy to agent tool calls, which helps with step six, and dependency scanning covers vulnerable packages inside the server itself.
Quick check
Can the model fix command injection by being careful?
No. The model's output is untrusted input. The server must enforce safe handling on its own.
Is a sandbox enough?
It limits the damage but does not remove the flaw. Use a sandbox and safe argument handling together.
Sources
- OWASP, Command Injection
- Model Context Protocol, Security Guidance
- OWASP LLM06:2025 Excessive Agency
Last reviewed: 18 October 2026.