We ran read-only static analysis over the tool-handler code of 26 public MCP (Model Context Protocol) servers. After excluding 3 that were clients or adapters rather than servers, 14 of 23 exposed at least one issue in a fixed six-class rubric. Every high-severity finding was independently re-verified against live code. Servers are anonymized — this reports prevalence, not named bugs.
Published 2026-08-08 · Author: WOWHOW · Method: GitHub-API static analysis, adversarial verification pass
Share of the 23 analyzed servers with at least one finding in each class. A server can appear in more than one row.
| Vulnerability class | Servers | Prevalence |
|---|---|---|
| Unauthenticated tool exposure | 7/23 | 30% |
| Path traversal / arbitrary file access | 6/23 | 26% |
| Missing input validation (incl. SQL injection) | 5/23 | 22% |
| Server-side request forgery (SSRF) | 4/23 | 17% |
| Secret / credential leakage | 2/23 | 9% |
Each analyzed server (S01–S23), its language and popularity tier, and the finding classes it exposed. Names are withheld by design; a finding tagged by design is a documented, intentional capability (e.g. a browser-automation tool), not an accidental bug.
| Server | Lang | Popularity | Findings |
|---|---|---|---|
| S01 | TypeScript | high (8k+★) | clean |
| S02 | TypeScript | high (8k+★) | powerful_tool_by_design (by design)UnauthenticatedServer-side |
| S03 | Go | high (8k+★) | clean |
| S04 | Python | high (8k+★) | PathMissing |
| S05 | TypeScript | high (8k+★) | Server-sideSecret |
| S06 | TypeScript | high (8k+★) | clean |
| S07 | Python | high (8k+★) | Path |
| S08 | TypeScript | mid (1.5k-8k★) | UnauthenticatedPath |
| S09 | TypeScript | mid (1.5k-8k★) | clean |
| S10 | TypeScript | mid (1.5k-8k★) | Unauthenticated |
| S11 | Python | mid (1.5k-8k★) | clean |
| S12 | TypeScript | mid (1.5k-8k★) | clean |
| S13 | Go/Python | mid (1.5k-8k★) | UnauthenticatedPath |
| S14 | TypeScript | mid (1.5k-8k★) | clean |
| S15 | TypeScript | mid (1.5k-8k★) | Unauthenticated |
| S16 | Go | mid (1.5k-8k★) | clean |
| S17 | Python | long-tail (<1.5k★) | Server-sideServer-sideServer-sidePathPathPathPathUnauthenticatedMissing |
| S18 | Python | long-tail (<1.5k★) | Path |
| S19 | Go | long-tail (<1.5k★) | MissingMissing |
| S20 | Python | long-tail (<1.5k★) | Missing |
| S21 | Python | long-tail (<1.5k★) | clean |
| S22 | Python | long-tail (<1.5k★) | UnauthenticatedMissingServer-side |
| S23 | TypeScript | long-tail (<1.5k★) | Secret |
The five issue classes above map to five fixes. Every one showed up as a preventable pattern in the servers that were clean.
Path(base) / user_path is discarded entirely when user_path is absolute; in Node, path.join does not stop ../ escapes.assert vanish under python -O — use real checks.An MCP server hands a language model real capability — file access, shell, database queries, outbound HTTP. When the transport is unauthenticated or a path argument is uncontained, the blast radius is not a chatbot giving a wrong answer; it is arbitrary file read, credential exfiltration, or requests made with your server's own keys. The long tail is where it concentrated: hardened official servers were mostly clean, while smaller community servers carried most of the high-severity findings.
If you run agents against MCP servers in production, the governance layer is the fix — we cover the patterns in MCP production hardening and least-privilege MCP governance. Building your own server? The TypeScript MCP build guide bakes these checks in, and the Claude Code Production Pack ships the rule files and agents that enforce them.