Keeping MCP Inspector Safe: Lessons from CVE‑2025‑49596
Written by Om-Shree-0709 on .
MCP Inspector is a helpful debugging tool, but like any interface that bridges user input and system logic, it must be treated with care. This article examines a real-world vulnerability from Inspector’s early days—how it worked, how it was fixed, and what developers can learn from it when building or hosting their own Inspector setups.
The Problem
In older versions of Inspector, the frontend UI could execute tool-use
requests locally using a user-provided manifest. This was useful for testing tools without running a full MCP server. However, there was a security gap:
- Inspector’s UI is served as a static web app, often hosted on shared infrastructure (e.g., a dev server or IPFS).
- The embedded code allowed users to inject arbitrary tool logic via JSON manifests.
- Those tool definitions were executed using
eval()
or unsafe deserialization under the hood.
This meant that someone could create a malicious manifest and trick another user into running code directly in their browser. In environments where Inspector was used to test against local or localhost-facing servers, this could be abused to access internal APIs or read sensitive local files1.
The Fix
The fix was simple but important: Inspector was changed to never allow local tool execution without explicit opt-in. Newer versions only load tool definitions from a trusted MCP server manifest. The UI was updated to reflect this as well:
- If no
proxy
WebSocket connection is present, the Tools tab is disabled. - Users can no longer paste in arbitrary tool definitions directly.
- Tool execution is sandboxed and isolated from the host browser2.
These changes closed the trust boundary and made Inspector safe to use in shared or remote setups.
The Takeaway for Developers
When building any developer-facing tool that interacts with runtime data or user-defined logic, treat untrusted input as code—even if it looks like plain JSON. Assume someone might copy and paste from Stack Overflow or a chat window. Validate inputs. Remove any use of eval()
or Function()
constructors.
This also means carefully separating “mock mode” from “live mode.” Mock testing is helpful but should be clearly sandboxed, with no overlap with real tool execution. In Inspector’s case, it now enforces this separation via the UI and underlying JSON-RPC behavior3.
Writing a Tool in TypeScript
Here’s a safe, real-world example of an MCP tool handler in TypeScript. This function summarizes text input using a fixed max length, including validation:
This tool will now only be called by the MCP server itself, based on validated JSON-RPC requests. The Inspector UI merely displays results—it does not run this logic directly4.
My Thoughts
Security issues like this aren’t rare in dev tools. What matters is how clearly the trust boundary is defined and enforced. I appreciate that Inspector now makes that boundary visible: the frontend only shows tools and prompts that the server defines. If anything goes wrong, it's traceable, and the browser stays safe.
References
Footnotes
Written by Om-Shree-0709 (@Om-Shree-0709)