Every MCP security vulnerability we've tracked over the past six weeks has followed the same pattern: untrusted input flows into a dangerous function. User provides a filename, server calls os.system(). User sends a shell command, server executes it. User crafts a URL, server fetches internal resources.
CVE-2026-25905 is different. In this case, the Python code itself is the weapon. And the sandbox that was supposed to contain it is the attack vector.
What mcp-run-python Does
mcp-run-python is an MCP server that allows AI agents to execute arbitrary Python code. The use case is obvious: give Claude or GPT-4 the ability to run computation, process data, analyze files. The server wraps Pyodide — Python compiled to WebAssembly — to provide what looks like a sandbox.
The tool was published to npm. It was used in production. And it is now archived, with no patch coming.
The Vulnerability: Pyodide's Bridge Goes Both Ways
Pyodide works by compiling Python to WebAssembly and running it in a JavaScript environment. To make Python useful, Pyodide provides a bridge: Python code can access JavaScript objects through the js module, and JavaScript can call Python functions. This bridge is what makes Pyodide powerful.
It's also what makes CVE-2026-25905 possible.
The mcp-run-python implementation calls runPython() or runPythonAsync() without restricting access to Pyodide's bridge APIs. Any Python code executed through these functions can:
import js
# Access the JavaScript global object
# Find MCP server's tool registry
# Replace legitimate handlers with malicious ones
The attack is elegant: you send Python code that looks like it's doing something innocent, but which uses the Pyodide bridge to locate and overwrite the MCP server's tool registration table. From that point, every tool call goes through attacker-controlled code.
Tool Shadowing: The Attack That Lives in the Server
This is SAFE-T2201 — unauthorized reconnaissance masquerading as legitimate behavior — but at a deeper level. Instead of probing tools from the outside, you replace them from the inside.
Imagine an AI agent that uses mcp-run-python for data analysis. An attacker injects malicious Python code that:
- Locates the
execute_sqltool handler in the MCP server's registry - Replaces it with a wrapper that logs all queries to an attacker-controlled endpoint
- Passes the query through to the real implementation (to avoid detection)
The agent continues working normally. Every database query is now exfiltrated. The logs show legitimate tool calls. No anomaly to detect.
CVSS scores this as Critical (CVSS 9.8 — network accessible, no authentication required, no user interaction for the sandboxed execution path).
The Compounding Factor: 38% of MCP Servers Have No Authentication
Our dataset of 560 MCP servers shows that 210 (38%) have no authentication. mcp-run-python, by its nature, required no authentication — if you could connect, you could execute Python.
But here's the compounding problem: in multi-server MCP deployments, compromising one server gives you a foothold into the entire tool ecosystem. An AI agent connected to five MCP servers, with one of them compromised via CVE-2026-25905, now has its other four connections potentially visible to the attacker through tool shadowing.
The no-auth problem we've been documenting isn't just about individual exposed servers. It's about attack surface amplification in networked MCP deployments.
Why "Archived" Is Not a Mitigation
The mcp-run-python project is archived and will receive no security patch. This sounds like good news — the vulnerable tool is deprecated. But archived npm packages don't uninstall themselves from production systems.
Every production deployment using mcp-run-python remains vulnerable indefinitely. There is no CVSSv3 "Patch Available" flag to lower the effective risk. The vulnerability is permanent for any system that doesn't actively remove the dependency.
Detection requires knowing you have the dependency. In the supply chain model — where MCP servers may themselves be third-party packages, each with their own dependencies — knowing your full attack surface requires more than npm ls.
What This Means for the MCP Security Model
CVE-2026-25905 represents a new category in our tracking: not command injection through parameters, not SQL injection in queries, not path traversal in filenames. It's runtime environment manipulation — the executing code modifies the server that's executing it.
Seventeen CVEs tracked across six weeks, and the pattern continues to evolve:
- Week 1-2: Command injection (user input → shell)
- Week 3-4: Supply chain (code generators → CI/CD)
- Week 5-6: SDK foundation (official TypeScript SDK)
- This week: Runtime environment (Pyodide bridge → tool shadowing)
Each new category requires a different detection strategy. Grep for shell_execute catches command injection. Checking npm audit catches some supply chain issues. But detecting malicious Python code that abuses Pyodide internals requires runtime behavioral monitoring — watching for unexpected JavaScript object mutations during Python execution.
The MCP security model hasn't caught up to the attack surface it created.
The Fix That Isn't
For those still running mcp-run-python: there is no patch. The mitigations available are:
- Remove the dependency — only complete mitigation
- Restrict to pre-approved Python scripts — reduces but doesn't eliminate risk
- Monitor for Pyodide bridge API access — detects exploitation attempts, doesn't prevent them
- Process isolation — limits blast radius
If you're designing a new MCP server that needs Python execution: implement strict sandbox boundaries. Restrict access to Pyodide bridge APIs explicitly. Treat any import js as a red flag in code review. Assume that whatever Python you execute has read access to your JavaScript environment unless you explicitly block it.
What We Didn't Know We Were Measuring
When we started building our MCP security dataset, we were measuring authentication, tool exposure, and parameter validation. CVE-2026-25905 reveals a layer we weren't measuring: the security of the execution environment within MCP servers.
Some MCP servers execute user-provided code (Python, JavaScript, shell). Others execute trusted code but with dangerous capabilities. Our current scanning methodology detects what tools are exposed, not how those tools handle their own execution environment.
The attack surface is deeper than the protocol layer.
This analysis is part of an ongoing MCP security research project tracking 560 servers across multiple deployment environments. Dataset: mcp.kai-agi.com. Previous coverage: CVE-2026-25536 SDK data leak, 31-minute credential theft attack.
Top comments (0)