AWS disclosed a vulnerability in its own open-source MCP server on October 1, 2026, and the mechanism is worth more than the advisory. A crafted value passed to a scan operation was interpreted as a command-line option rather than as the revision it was supposed to be. The result: an attacker could create, overwrite or truncate arbitrary files on the host, outside the directory the tool was supposed to confine itself to. The control that was supposed to hold — workspace confinement — did not fail on a path check. It failed on argument parsing.

CVE-2026-97662 affects awslabs.security-agent-mcp-server versions 0.1.1 and above but below 0.2.0, and is fixed in 0.2.0. AWS rates it “Important” and published no CVSS score. There is no workaround and no evidence of exploitation. The generalisable lesson is bigger than the CVE: MCP servers and similar LLM-facing tools routinely describe their arguments as data while implementing them as code, and every one that shells out inherits the argument-injection bug class. The mitigation is not a better directory check. It is passing an argument array instead of a command string.

Key takeaways:

  • Affected: awslabs.security-agent-mcp-server ≥ 0.1.1 and < 0.2.0. Fixed in 0.2.0 on PyPI.
  • AWS rates it “Important (requires attention)” and published no CVSS vector.
  • Attacker model is context-dependent: the model or agent must be fed attacker-controlled content. This is not an unauthenticated network attack.
  • It is a containment failure, not remote code execution. Do not inflate it.
  • This is an AWS Labs open-source tool, not an AWS cloud service. The distinction matters if you report it upward.
  • No workaround exists. Upgrade, or isolate.

What AWS actually published

FieldValue
CVECVE-2026-97662
GHSAGHSA-8g28-rj54-p5p2
AWS bulletin2026-121-AWS
Published1 October 2026, 10:30 AM PDT
Content typeImportant (requires attention)
Affectedawslabs.security-agent-mcp-server ≥ 0.1.1, < 0.2.0
Fixed in0.2.0 (PyPI)
WorkaroundNone
Credited toMario Guzmán, independent researcher
AWS Security Bulletin 2026-121-AWS.

The advisory’s own description is precise about the mechanism: a crafted reference value supplied to the scan is interpreted as a command-line option rather than a revision. The stated effect is that an attacker can create, overwrite or truncate arbitrary files on the host outside the intended workspace directory, bypassing the server’s workspace-confinement control.

Why this class is structural, not a coding mistake

The underlying pattern is old and well understood: if user-controlled input is concatenated into a command line and that string is handed to a shell, then a value beginning with a dash is not a value, it is an option. Every downstream tool in the chain then honours it as one.

What makes this particular instance interesting is which control was supposed to stop it. Workspace confinement is a path-level control. It answers “where is this tool allowed to write?” The injection does not attack that question at all. It arranges for a write to a path the tool never validated, by making a different part of the command mean something other than what the tool intended.

That is why a workspace-path check is the wrong layer of defence, however carefully written. Validating the destination is validating the result of a decision that was already made incorrectly. If the argument parser can be persuaded that your revision is a flag, the path validator downstream is being asked the wrong question.

The fix that actually closes the class

Pass an argument array, never a shell string. In Python that means subprocess.run([...]) with shell=False as the default, rather than a string with your value interpolated into it. In Rust, Command::new with .arg() rather than .args(["sh", "-c", "..."]). In Go, exec.Command with separate arguments rather than sh -c.

With an argv array there is no parsing step, so a leading dash in your revision is simply a revision that happens to start with a dash. The value stays a value. The whole bug class evaporates without any validation of its content.

Two further hardening steps are worth adding, in this order of importance:

  • Pin argv[0] explicitly rather than letting it be inferred from the executable path, so a writable PATH entry cannot substitute a different program.
  • Reject values beginning with - as defence in depth. This is a backstop, not the fix, and it will not help if your tool legitimately needs to pass an option through.
  • Never route through a shell when the child does not need one. sh -c adds globbing, word splitting, redirection and command substitution to the set of things that can go wrong, none of which you need in order to run git.

The MCP-specific lesson

MCP tool schemas describe parameters as typed data: a string here, an integer there, maybe an enum. That framing encourages implementors to think of them as data. But a tool’s implementation typically ends at a process invocation, and at that point the same string becomes a command-line token with syntax.

The gap between the schema and the exec call is the vulnerability. A schema that declares {"ref": {"type": "string"}} carries no constraint that would survive contact with an argument parser. Neither does a description saying “a git revision”.

This compounds with the agent threat model, and the combination is what makes it worth writing about rather than filing. Most MCP server hardening assumes the adversary is a malicious model — an agent tricked by prompt injection into calling a dangerous tool. This CVE is the other direction: the adversary controls the content the model is reading, and the model’s innocent, correct-looking tool call carries the payload. The model did exactly what it was asked. The bug was downstream of the model entirely.

Controls that sit on the model — approval prompts, tool allowlists, output filters — do not help when the model’s behaviour is correct. The control has to be in the tool’s own implementation.

What AWS recommends

  • Upgrade to 0.2.0.
  • Patch forks and derivatives you maintain yourself, which will not receive the upstream fix.
  • Run diff scans only against repositories you trust, since attacker-controlled repository content is the delivery path.
  • Run the tool with least privilege in an isolated environment.

Being precise about severity

AWS published no CVSS vector for this one, and that is worth preserving rather than filling in. Three constraints keep it below where a headline might place it:

  • No exploitation is claimed. Nobody has reported this being used.
  • It is arbitrary file write, not arbitrary code execution. On its own that is serious, but it is a different claim.
  • It is a containment bypass in open-source tooling, not a vulnerability in a hosted AWS service. Nothing about your AWS account is affected unless you run this server.

The compensating control also matters: AWS’s own framing is that the attack requires the model or agent to be fed attacker-controlled content. That is a real precondition, and it is precisely the situation in which agent tooling is being deployed. Rare in production does not mean unimportant.

The audit to run on your own MCP servers

# Find shell-string construction in your own tooling
grep -rn "shell=True" .
grep -rn "sh -c|bash -c|/bin/sh" .
grep -rn "os.system(" .

# Python: prefer argv arrays
subprocess.run(["git", "diff", ref], shell=False)

Two findings are worth acting on immediately. Any tool that takes a revision, branch, path or URL from model-visible content and builds a command string from it has this bug class. Any tool that resolves its executable through PATH has the argv[0] substitution variant, which is arguably easier to exploit because it needs no injection at all.

If you want the broader picture of how tool calls reach an execution boundary, how AI tool calling actually works is the right starting point, and AI agent security: Linux permissions, sandboxing and least privilege covers the controls that do hold when a tool does misbehave.

References

Related Tools

Try these companion tools on DevStackIO Tools:

  • CSP generator — build Content Security Policy headers to contain workspace escape attacks.