An AST-level audit of 100 production TypeScript MCP servers found 445 security findings across 70 servers, including 35 critical findings from 11 servers.
2
MCPeek uses TypeScript ASTs and multi-pass taint tracking to follow tool inputs into dangerous sinks such as exec, fetch, and database queries.
3
Static analysis can catch source-level issues such as command injection and path traversal, but it does not replace dynamic or runtime testing for MCP-specific attacks.
Summary
Akash Sathish examines MCP security before an agent makes its first tool call. He describes how malicious instructions can enter through prompts, connected MCP servers, or retrieved documents, then shows how an LLM can steer an MCP server toward dangerous behavior. His audit of 100 widely installed TypeScript MCP servers found 445 findings across 70 servers. The examples include command injection, path traversal, SSRF, and tool poisoning. Sathish argues that existing scanners often miss MCP-specific problems because they focus on runtime behavior, hide relevant features behind paid editions, or were not designed for MCP. He presents MCPeek, an offline open-source scanner built with ts-morph. It discovers MCP tool handlers, builds an AST, tracks tainted inputs across variables and user-defined helper functions, and emits Markdown, JSON, or SARIF reports. He is clear about the limits: static scanning is an early gate, while dynamic and runtime controls are still needed.
MCP servers can be steered by instructions that enter outside the tool call
Sathish describes MCP as a powerful component that takes orders from a non-deterministic LLM. An attacker can place instructions in an agent prompt, agent code, another connected MCP server, or a document retrieved by an MCP server. His GitHub issue example shows a server retrieving content correctly while the LLM follows a malicious instruction embedded in that content. The resulting behavior can affect the original server and other connected servers. The risk comes from the interaction between ordinary server behavior and an agent that may follow instructions blindly.
Ordinary source-code flaws can become serious MCP vulnerabilities
Sathish uses a command-running tool to show how code can look acceptable at a glance. A user-controlled string reaches a shell execution function without meaningful sanitization. Because the LLM can generate the command, the tool can run arbitrary shell commands in the server environment. He connects this pattern to reported incidents involving MCP servers, including arbitrary command execution, tool poisoning, email leakage, and path traversal. He also describes file and repository access that allowed an LLM to reach locations the tool should not expose.
The audit found widespread findings in production TypeScript servers
Sathish says he scanned 100 production TypeScript MCP servers and found 445 findings across 70 servers. The reported severity counts were 35 critical, 41 high, and 69 medium. All 35 critical findings came from 11 of the 100 servers. His heat map groups findings by vulnerability class and shows input validation at the top, followed by other familiar classes. He argues that these are established vulnerability types, which raises a basic question about why source-level checks did not catch them before deployment.
Existing scanners leave gaps because MCP was not their design target
Sathish says current MCP security scanners focus mainly on runtime vulnerabilities. Traditional static analysis is available, but he identifies two barriers. Relevant capabilities in popular tools may be unavailable in community editions, and those tools were not built around MCP-specific vulnerabilities. He therefore wants a scanner that needs no account, cloud service, or model call, while understanding MCP tool handlers and the way their inputs reach code that can cause harm.
AST analysis gives the scanner program structure instead of isolated patterns
Regular expressions can either miss vulnerabilities or produce too many false positives, especially when the meaning of code depends on several snippets working together. Sathish uses an abstract syntax tree to preserve variables, symbols, types, and relationships in TypeScript source. He builds MCPeek with ts-morph, which converts source code into a structure the scanner can inspect. This lets the scanner follow a variable even when its name, object, or surrounding code changes, rather than matching only a fixed dangerous pattern.
Taint tracking follows tool input into dangerous sinks
MCPeek treats input entering an MCP tool as tainted by default. The taint propagates through assignments, strings, and other code paths. The scanner then checks whether the value reaches a sink such as a database query, fetch call, or exec function without a guard or sanitization step. Sathish says MCP's relatively simple structure makes a purpose-built scanner practical because there is a clear tool entry point. MCPeek also follows one hop into user-defined helper functions across files, while skipping popular libraries to reduce false positives.
MCPeek produces reports that developers and CI systems can use
The scanner can inspect a local directory or a list of repositories. It removes tests, examples, and demo folders before focusing on source files, then builds the AST and runs taint analysis. Each finding includes the violated rule, source location, severity, and taint chain. MCPeek can emit Markdown, JSON, and SARIF. The SARIF output includes a CWE number and can connect findings to GitHub Code Scanning. Sathish also notes that the taint-chain structure can help an AI-based fix bot understand where a vulnerability flows through the code.
Static scanning is an early gate, not a complete MCP security system
In the demo, MCPeek catches a command injection issue in a tool that passes a command directly to shell execution. It also catches path traversal in a file-reading tool without base-directory containment. The fixed version restricts commands to the intended operation and resolves and checks paths against the expected directory. Sathish then states that static analysis will not catch every dynamic MCP attack, including problems discussed in other MCP security research. He recommends running it during development and in CI, while keeping dynamic and runtime security controls in place.
"The biggest advantage of utilizing this type of algorithm in MCP server is that in normal web frameworks there are multiple entry points. But in case of MCP server, there's just one entry point."12:02
Who should watch
You maintain or review TypeScript MCP servers and need a source-level check for tool inputs reaching shell, file, network, or database operations.
Your team is adding MCP tools to a CI workflow and wants offline findings with taint paths and SARIF output.
You already use runtime MCP security controls and want to understand what static analysis can catch before deployment, as well as where it stops.