Checks catalogue · v0.1

Every check, what it probes, and how often it is wrong.

37 catalogue entries, generated from the scanner itself (mcpprobe 0.3.7) and mapped to OWASP MCP Top 10 (beta), Agentic Top 10 and LLM Top 10 (2026 and 2025). The 24 passive checks run today and never call a tool. The 8 active checks are registered behind the authorisation gate and coming soon. Governance items are listed so you know what a scan cannot see.

Showing 37 of 37 checks

Authentication

AUTH-01 … AUTH-06

Unauthenticated endpoints, RFC 9728 protected-resource metadata, PKCE S256 and HTTPS on the authorization server, and tokens with the wrong audience or issuer.

Authentication checks with probe, mode, default severity, framework mapping and false-positive rate
IDCheckWhat it doesModeSeverityMaps toFP rate
AUTH-01Remote MCP endpoint accepts requests without authenticationPOSTs initialize (or server/discover) and tools/list with no Authorization header.
Details and fix

POSTs initialize (or server/discover) and tools/list with no Authorization header. If the server answers with a tool list, anyone who can reach the endpoint can drive its tools. When the operator supplies credentials with --header, one extra request is sent with those credentials removed, so a protected server is not misreported. Passes only when the endpoint answers 401/403 without credentials.

Evidence: The unauthenticated request (Authorization shown as not sent) and the response.

False positives: Servers protected by a network boundary (VPN, mTLS at a proxy, IP allow-list) will still be flagged because the scanner only sees what the endpoint returns. Local development servers bound to loopback are reported at reduced severity but are still exposed to DNS-rebinding and browser-based attacks (see CVE-2025-49596 class).

Fix: Put the endpoint behind OAuth 2.1 as described in the MCP authorization spec: return 401 with WWW-Authenticate: Bearer resource_metadata="<RFC 9728 metadata URL>", validate each token's signature, issuer, expiry and audience, and reject requests without a valid bearer token. Authentication does not make a dangerous tool safe.

passivehttpHighMCP07:2025 (beta) · ASI03 · LLM04:2026 · LLM03:2026 · LLM03:2025 · LLM06:2025Pending
AUTH-02Protected resource metadata (RFC 9728) missing or invalidParses WWW-Authenticate for resource_metadata (when the server answers 401), then tries /.well-known/oauth-protected-resource[/path] and the host root.
Details and fix

Parses WWW-Authenticate for resource_metadata (when the server answers 401), then tries /.well-known/oauth-protected-resource[/path] and the host root. The document must be JSON with a non-empty authorization_servers list. Without it, conformant clients cannot start the OAuth flow and users are pushed toward pasting long-lived static tokens. A server that requires no authentication and serves no metadata is reported too (medium, the discovery half of AUTH-01).

Evidence: The 401 response headers and each metadata GET with its status.

False positives: Servers that use a non-OAuth scheme (API keys at a gateway) will be flagged; the MCP spec still expects RFC 9728 metadata for HTTP transports. A deliberately public, read-only server with no authentication will also be flagged; AUTH-01 is the root cause.

Fix: Serve /.well-known/oauth-protected-resource (path-aware variant preferred) with 'resource' and 'authorization_servers', and include WWW-Authenticate: Bearer resource_metadata="<url>" on every 401.

passivehttpHighMCP07:2025 (beta)Pending
AUTH-03Authorization server metadata weak or missing (PKCE S256 / HTTPS)For each authorization server listed in the protected resource metadata, fetches /.well-known/oauth-authorization-server (RFC 8414, path-aware) then /.well-known/openid-configuration.
Details and fix

For each authorization server listed in the protected resource metadata, fetches /.well-known/oauth-authorization-server (RFC 8414, path-aware) then /.well-known/openid-configuration. Flags a missing document, a code_challenge_methods_supported list without S256 (MCP clients MUST refuse to proceed), and non-HTTPS endpoints. This may make one GET to a third-party host; disable with --no-follow-as.

Evidence: Each metadata GET with status and body.

False positives: Some authorization servers support PKCE but omit code_challenge_methods_supported; per the MCP spec that is still a conformance failure for clients.

Fix: Publish RFC 8414 metadata with code_challenge_methods_supported including S256 and HTTPS-only endpoints. If you use a third-party identity provider, confirm it exposes the metadata document at the issuer URL you advertise.

passivehttpHighMCP07:2025 (beta) · MCP01:2025 (beta)Pending
AUTH-04Server accepts a self-minted token with the wrong audience/issuerMints two syntactically valid JWTs the server cannot have issued (HS256 with a random scanner key, and alg=none) with a foreign issuer and audience, and presents them as Bearer tokens.
Details and fix

Mints two syntactically valid JWTs the server cannot have issued (HS256 with a random scanner key, and alg=none) with a foreign issuer and audience, and presents them as Bearer tokens. Any non-401/403 answer means the server is not validating signature or audience (RFC 8707). Also presents the token in the access_token query parameter, which the spec forbids. Only self-minted tokens are used; no real credentials.

Evidence: Each probe request (token redacted) and the response status/body.

False positives: A proxy that strips Authorization and answers 200 for health reasons could be flagged; check the response body in the evidence actually contains an MCP result.

Fix: Validate the token signature against the authorization server's keys, require 'aud' to equal this server's canonical URI (RFC 8707), reject alg=none, and never read tokens from query strings.

passivehttpCriticalMCP07:2025 (beta) · MCP01:2025 (beta) · ASI03Pending
AUTH-05Authorization server does not advertise RFC 9207 iss support (2026-07-28)2026-07-28 says MCP authorization servers SHOULD include the RFC 9207 'iss' parameter in authorization responses and, when they do, MUST advertise authorization_response_iss_parameter_supported: true in their metadata; clients reject a response without iss only when that flag is true.
Details and fix

2026-07-28 says MCP authorization servers SHOULD include the RFC 9207 'iss' parameter in authorization responses and, when they do, MUST advertise authorization_response_iss_parameter_supported: true in their metadata; clients reject a response without iss only when that flag is true. Reads the authorization server metadata AUTH-03 already fetched and reports a flag that is absent or not true. Sends nothing. The revision says this SHOULD is expected to become a MUST.

Evidence: The authorization server metadata document AUTH-03 fetched.

False positives: The spec allows a server to emit iss before it updates its metadata; such a server is reported until the flag is published, because clients key their rejection on the flag.

Fix: Include iss in every authorization response, error responses too (RFC 9207 section 2), and publish "authorization_response_iss_parameter_supported": true in the authorization server metadata (https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization#authorization-response-validation). With a hosted identity provider, enable its issuer-identification option.

passivehttpLowMCP07:2025 (beta)Pending
AUTH-06Deprecated Dynamic Client Registration offered (2026-07-28)2026-07-28 deprecates OAuth Dynamic Client Registration (RFC 7591) in favour of Client ID Metadata Documents, which authorization servers SHOULD support.
Details and fix

2026-07-28 deprecates OAuth Dynamic Client Registration (RFC 7591) in favour of Client ID Metadata Documents, which authorization servers SHOULD support. Reads the authorization server metadata AUTH-03 already fetched: a registration_endpoint without client_id_metadata_document_supported: true is low (clients have only the deprecated path); a registration_endpoint next to CIMD support is informational (kept for backwards compatibility). No registration request is sent.

Evidence: The authorization server metadata document AUTH-03 fetched.

False positives: Keeping DCR for older clients is allowed; the informational finding is a reminder to plan its removal, not a defect. An authorization server that supports neither DCR nor CIMD (pre-registration only) is not reported here.

Fix: Support Client ID Metadata Documents and advertise "client_id_metadata_document_supported": true; keep registration_endpoint only while older clients still need it, and plan its removal (https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/client-registration). Open registration endpoints also deserve rate limits and redirect-URI validation.

passivehttpLowMCP07:2025 (beta)Pending

Transport

TRANS-01 … TRANS-09

Origin validation (DNS rebinding), protocol-version handling, session-id quality and forgery, deprecated HTTP+SSE, TLS and security headers.

Transport checks with probe, mode, default severity, framework mapping and false-positive rate
IDCheckWhat it doesModeSeverityMaps toFP rate
TRANS-01Origin header not validated (DNS-rebinding exposure)Sends a normal negotiation request with 'Origin: https://evil.example' and one with 'Origin: null'.
Details and fix

Sends a normal negotiation request with 'Origin: https://evil.example' and one with 'Origin: null'. The transport spec says servers MUST validate Origin and return 403 on an invalid one; otherwise a web page can drive the server through the victim's browser (DNS rebinding). Requests without an Origin header are not tested: non-browser clients do not send one.

Evidence: Each POST with a foreign Origin header and the non-403 response.

False positives: If the server answers 401 (or 429) before looking at Origin the check is not applicable and says so. Reverse proxies that strip Origin will cause a finding against the proxied endpoint even if the application validates it.

Fix: Reject any request whose Origin header is present and not on an allow-list with HTTP 403, before processing the body, including 'Origin: null'. Allow requests with no Origin header.

passivehttpMediumMCP07:2025 (beta)Pending
TRANS-02Unsupported MCP-Protocol-Version header not rejectedSends a request with 'MCP-Protocol-Version: 1999-01-01'.
Details and fix

Sends a request with 'MCP-Protocol-Version: 1999-01-01'. The spec requires HTTP 400 (or, on 2026-07-28, an UnsupportedProtocolVersionError). Accepting any version string suggests the server ignores version negotiation entirely.

Evidence: The request with the bogus version header and the response.

False positives: Pre-2025-06-18 servers never defined the header, so an older server that ignores it is noted at low severity only. A 401/429 before the header is read makes the check not applicable.

Fix: Validate the MCP-Protocol-Version header against the versions you support and reply 400 when it is unknown. Separately, when initialize asks for a protocolVersion you do not support, answer with the latest version you do support and let the client decide; never echo back whatever the client asked for.

passivehttpLowMCP spec conformance / hygiene (no OWASP item)Pending
TRANS-03Weak, predictable or unvalidated Mcp-Session-IdCollects three session IDs from repeated initialize requests and checks length, character set, Shannon entropy and sequentiality.
Details and fix

Collects three session IDs from repeated initialize requests and checks length, character set, Shannon entropy and sequentiality. Then sends tools/list with a random forged session ID, expecting 400 or 404. Only runs on handshake revisions that issue Mcp-Session-Id (sessions were removed in 2026-07-28).

Evidence: The initialize responses (session header) and the forged-session request.

False positives: Entropy is estimated from three samples, so the test is conservative: only IDs shorter than 16 characters, obviously sequential, or with very low per-character entropy are flagged.

Fix: Generate session IDs with a CSPRNG (at least 128 bits, e.g. UUIDv4 or 32 random bytes base64url), store them server-side, and answer 404 for unknown IDs.

passivehttpHighMCP07:2025 (beta)Pending
TRANS-04Deprecated HTTP+SSE (2024-11-05) transport in useReports when the endpoint answers a GET with an SSE 'endpoint' event, i.e.
Details and fix

Reports when the endpoint answers a GET with an SSE 'endpoint' event, i.e. the 2024-11-05 HTTP+SSE transport that was deprecated in 2025-03-26 and formally classified Deprecated in 2026-07-28. Also noted when the negotiated revision predates 2025-06-18.

Evidence: The GET request and the first SSE event.

False positives: Informational only.

Fix: Migrate to Streamable HTTP (single endpoint, POST per message) and current protocol revision.

passivehttpInfoMCP spec conformance / hygiene (no OWASP item)Pending
TRANS-05Plain HTTP, weak TLS or missing security headersFlags non-loopback endpoints served over plain HTTP (bearer tokens in clear), TLS versions below 1.2 observed on the connection, and missing Strict-Transport-Security / X-Content-Type-Options headers on the MCP endpoint responses.
Details and fix

Flags non-loopback endpoints served over plain HTTP (bearer tokens in clear), TLS versions below 1.2 observed on the connection, and missing Strict-Transport-Security / X-Content-Type-Options headers on the MCP endpoint responses.

Evidence: Response headers of the negotiation/tools/list exchange and the observed TLS version.

False positives: Loopback plain-HTTP is reported as informational. Header checks look at the MCP endpoint only; a CDN may add headers on other paths.

Fix: Serve the endpoint over HTTPS with TLS 1.2+ only, add Strict-Transport-Security and X-Content-Type-Options: nosniff. Where an edge (API Gateway, CloudFront, Cloudflare, Vercel) is detected the fix text says where to configure it.

passivehttpHighMCP01:2025 (beta)Pending
TRANS-06server/discover result incomplete (2026-07-28)A 2026-07-28 server MUST implement server/discover.
Details and fix

A 2026-07-28 server MUST implement server/discover. The scanner's first request is server/discover; when it is answered, its result is checked for what the revision requires: supportedVersions (a list of version strings that includes the 2026-07-28 revision the request was served under), a capabilities object and resultType 'complete'. A missing _meta['io.modelcontextprotocol/serverInfo'] (SHOULD) is reported as informational. Caching hints on the same result are checked by TRANS-09. Not applicable to servers that speak an earlier revision through initialize.

Evidence: The fingerprinting server/discover request and its complete result.

False positives: A server that answers server/discover under an earlier result shape (for example a 'protocolVersions' key from a pre-release draft) is reported, because 2026-07-28 clients read 'supportedVersions'.

Fix: Return the DiscoverResult defined in the 2026-07-28 schema: {"resultType":"complete","supportedVersions":["2026-07-28", ...],"capabilities":{...},"_meta":{"io.modelcontextprotocol/serverInfo":{"name":...,"version":...}},"ttlMs":...,"cacheScope":"public"} (https://modelcontextprotocol.io/specification/2026-07-28/server/discover).

passivehttp, stdioLowMCP spec conformance / hygiene (no OWASP item)Pending
TRANS-07Protocol version the server does not advertise is accepted (downgrade)Takes supportedVersions from the server/discover result and sends one more server/discover declared (in _meta and in the MCP-Protocol-Version header) as the newest earlier revision the server does not list (2025-11-25, 2025-06-18 or 2025-03-26).
Details and fix

Takes supportedVersions from the server/discover result and sends one more server/discover declared (in _meta and in the MCP-Protocol-Version header) as the newest earlier revision the server does not list (2025-11-25, 2025-06-18 or 2025-03-26). The spec says a server that does not implement the requested version MUST answer HTTP 400 with UnsupportedProtocolVersionError (-32022). Serving the request anyway means a client or intermediary can push the server onto a revision it claims not to support, without the header validation and other protections of 2026-07-28. One request, no tool is called.

Evidence: The server/discover result (supportedVersions) and the downgraded request with its response.

False positives: A dual-era server that does serve the older revision but forgot to list it is reported too; listing it in supportedVersions is then the fix. Not applicable when every earlier revision is advertised.

Fix: Reject any request whose declared protocol version is not in your supportedVersions with HTTP 400 and {"code":-32022,"message":"Unsupported protocol version","data":{"supported":[...],"requested":"..."}}, before doing any work (https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning). If you do serve the older revision, list it in supportedVersions.

passivehttpLowMCP spec conformance / hygiene (no OWASP item)Pending
TRANS-08Mcp-Method header not validated against the request body (2026-07-28)2026-07-28 requires clients to mirror the JSON-RPC method into an Mcp-Method header, and servers that process the body MUST reject a request whose headers are missing or do not match the body with HTTP 400 and HeaderMismatch (-32020); otherwise a gateway that routes, rate-limits or authorises on the header can be bypassed by a body that says something else.
Details and fix

2026-07-28 requires clients to mirror the JSON-RPC method into an Mcp-Method header, and servers that process the body MUST reject a request whose headers are missing or do not match the body with HTTP 400 and HeaderMismatch (-32020); otherwise a gateway that routes, rate-limits or authorises on the header can be bypassed by a body that says something else. Sends two server/discover requests: one with 'Mcp-Method: tools/list' and one with no Mcp-Method header. Mcp-Name is not tested, because it is only defined for tools/call, resources/read and prompts/get, which a passive scan does not send.

Evidence: Both probe requests (headers shown) and their responses.

False positives: A server that rejects the probes with another 4xx is reported as informational only. When a gateway in front rejects mismatches itself, the finding concerns the server behind it only if the gateway can be bypassed.

Fix: Before dispatching, compare Mcp-Method (and, for tools/call, resources/read and prompts/get, the decoded Mcp-Name) with the body; when a required header is missing or differs, answer HTTP 400 with {"code":-32020,"message":"Header mismatch: ..."} (https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http#server-validation).

passivehttpMediumMCP spec conformance / hygiene (no OWASP item)Pending
TRANS-09ttlMs / cacheScope caching hints missing or invalid (2026-07-28)2026-07-28 servers MUST include caching hints on complete results of server/discover, tools/list, prompts/list and resources/list (among others): ttlMs, a number of milliseconds that MUST be >= 0, and cacheScope, either 'public' or 'private'.
Details and fix

2026-07-28 servers MUST include caching hints on complete results of server/discover, tools/list, prompts/list and resources/list (among others): ttlMs, a number of milliseconds that MUST be >= 0, and cacheScope, either 'public' or 'private'. Checks the results the scan already received; sends nothing. A missing cacheScope leaves shared gateways to guess whether a list may be served to other users.

Evidence: The server/discover and list results the scan already received.

False positives: Only the first page of each list is checked. A public cacheScope on an authenticated server is allowed by the spec when the list is the same for every user, so it is not reported.

Fix: Add "ttlMs": <milliseconds, >= 0> and "cacheScope": "public" (identical for every user) or "private" (depends on the caller's authorization) to every cacheable result (https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/caching).

passivehttp, stdioLowMCP spec conformance / hygiene (no OWASP item)Pending

Tool metadata

META-01 … META-07

Tool-description poisoning, rug-pull diffs against a stored baseline, annotations that contradict capability, schema hygiene and secrets in metadata.

Tool metadata checks with probe, mode, default severity, framework mapping and false-positive rate
IDCheckWhat it doesModeSeverityMaps toFP rate
META-01Possible tool-description poisoningScans every tool, prompt and resource description, every inputSchema parameter description and the server 'instructions' for: prompt-style markup (<IMPORTANT>, <system>, HTML comments), instructions aimed at the model (conceal from the user, ignore previous instructions, claim precedence over every other tool or over what the user asks, redirect/replace), requests to send the model's context out (conversation, chat history, system prompt, previous messages), requests to harvest secrets (the user's API key, token, password, credentials, .env), credential file paths next to a read/send verb, wording that changes what another tool does (shadowing), URLs and e-mail addresses with send/BCC wording, base64 blobs, zero-width/bidi/tag Unicode, mixed-script homoglyphs and excessive length.
Details and fix

Scans every tool, prompt and resource description, every inputSchema parameter description and the server 'instructions' for: prompt-style markup (<IMPORTANT>, <system>, HTML comments), instructions aimed at the model (conceal from the user, ignore previous instructions, claim precedence over every other tool or over what the user asks, redirect/replace), requests to send the model's context out (conversation, chat history, system prompt, previous messages), requests to harvest secrets (the user's API key, token, password, credentials, .env), credential file paths next to a read/send verb, wording that changes what another tool does (shadowing), URLs and e-mail addresses with send/BCC wording, base64 blobs, zero-width/bidi/tag Unicode, mixed-script homoglyphs and excessive length. Ordinary usage guidance ("always use this tool to...", "you must call X first") is not an indicator on its own; it raises a finding to high when combined with another instruction category. Findings carry tiered confidence and are never rated Critical on heuristics alone. Precision is guarded in the test-suite by thousands of real descriptions from published MCP servers (docs/benchmark.md).

Evidence: The tools/list (or prompts/resources/initialize) response and the matched excerpts.

False positives: Legitimate text that claims precedence over every other tool ('call this before any other tool whenever...') is reported at medium. Plain URLs, sibling-tool mentions and usage guidance are not reported; a credential path without a read/send verb is low. Review the matched excerpts; a second-opinion judge can be plugged in through the Python API (ScanOptions.judge); mcpprobe itself makes no LLM calls.

Fix: Rewrite the description so it only says what the tool does. Remove every instruction addressed to the model (when to call it, what to call first, what to hide from the user) and every request to pass along conversation, prompts, files or credentials. Strip invisible Unicode and HTML comments, and never reference other servers' tools. Pin and hash approved descriptions in clients (see META-02).

passivehttp, stdioHighMCP03:2025 (beta) · ASI01 · ASI04 · LLM01:2026 · LLM01:2025Pending
META-02Tool surface changed since the stored baseline (rug-pull indicator)Computes SHA-256 over the canonical JSON of each tool, prompt and resource definition and the server instructions.
Details and fix

Computes SHA-256 over the canonical JSON of each tool, prompt and resource definition and the server instructions. With --baseline FILE the current snapshot is compared to the stored one and any added, removed or changed definition is reported (a changed description after approval is the classic 'rug pull'). The snapshot is then written back to the file. Also notes when the server advertises tools.listChanged.

Evidence: The current tools/list response plus per-item hashes and the diff.

False positives: Any legitimate release that edits a description will trigger the diff; the finding says what changed so the reviewer can decide. Servers that embed timestamps or random data in descriptions will change on every scan.

Fix: Treat tool definitions as code: version them, review changes, and have clients pin and re-approve definitions when the hash changes.

passivehttp, stdioMediumMCP03:2025 (beta) · ASI04n/a (diff)
META-03Dangerous tool capability exposedClassifies each tool by name, description and parameter names into capability classes.
Details and fix

Classifies each tool by name, description and parameter names into capability classes. Tools that advertise arbitrary command execution, arbitrary file read or arbitrary file write (a shell/file capability selected by a free-form string argument with no enum, const or pattern) are rated high on their own and critical when the remote endpoint needs no authentication. The remaining high-impact surface (network, e-mail, credentials, payments) is summarised at low severity. Annotations that contradict the capability are reported by META-06 (until 0.2 they were reported here). Passive scanning sees the advertised capability, not whether the implementation really executes: the rating is based on the name, description and schema, and no tool is called.

Evidence: The tools/list response; each affected tool's complete definition is shown as proof.

False positives: Classification is keyword-based: a tool named 'delete_draft' that only removes the user's own draft will be classed 'delete'. A tool that advertises a shell but whose implementation is a stub is still reported, because clients and models act on the advertised capability. Since 0.3.4 lookup tools (names built from get/search/describe and no action verb, such as 'get_cli_command') are only rated as command execution or file read when their description says they execute something or read files. The critical rating assumes tools/call is as open as tools/list; a server that gates tools/call with an API key the handshake does not require (and declares it in its registry entry) is rated high, not critical, in the registry survey since 0.3.5.

Fix: For arbitrary command execution or file access: remove the tool, or sandbox it and replace the free-form argument with an allow-list (enum) of commands or files. Annotations come after that (META-06); they help a careful client warn the user but do nothing about the risk.

passivehttp, stdioHighMCP02:2025 (beta) · MCP05:2025 (beta) · ASI02 · ASI05 · LLM03:2026 · LLM06:2025Pending
META-04Tool schema hygiene problemsChecks tool names against [A-Za-z0-9_.-]{1,128} and for duplicates; checks that inputSchema is a JSON Schema object of type 'object'; flags free-form string arguments whose names suggest paths, commands, URLs or queries and that carry no enum, pattern, format or maxLength constraint.
Details and fix

Checks tool names against [A-Za-z0-9_.-]{1,128} and for duplicates; checks that inputSchema is a JSON Schema object of type 'object'; flags free-form string arguments whose names suggest paths, commands, URLs or queries and that carry no enum, pattern, format or maxLength constraint. One finding lists every affected tool, with each tool's complete inputSchema and its specific problems (including arguments missing from 'required' and additionalProperties not set to false). Missing outputSchema cannot be judged without calling the tool and is not reported.

Evidence: The tools/list response; each affected tool's complete inputSchema is shown as proof.

False positives: An unconstrained 'query' string is often unavoidable (search tools); the finding is Low severity and meant as a review prompt, not a defect.

Fix: Constrain every risky string argument (enum for a fixed set, pattern for a format, maxLength to bound size), list required arguments in 'required', set additionalProperties: false, and validate arguments on the server against the same schema instead of trusting the client to have done it.

passivehttp, stdioLowMCP05:2025 (beta)Pending
META-05Secret material in server metadata or configurationPattern and entropy scan for AWS/GitHub/Slack/Stripe/Google keys, private key blocks, JWTs, bearer tokens, connection strings with passwords and generic 'key=...' assignments across tool/prompt/resource descriptions, parameter descriptions, resource URIs, server instructions and, for stdio targets, the command line and environment supplied to the scanner.
Details and fix

Pattern and entropy scan for AWS/GitHub/Slack/Stripe/Google keys, private key blocks, JWTs, bearer tokens, connection strings with passwords and generic 'key=...' assignments across tool/prompt/resource descriptions, parameter descriptions, resource URIs, server instructions and, for stdio targets, the command line and environment supplied to the scanner. Matched values are redacted in the report.

Evidence: The listing response that contained the match; values redacted.

False positives: Published sample keys (the AWS keys ending in EXAMPLE, the Stripe and jwt.io documentation samples) and obvious placeholders are skipped since 0.3.4; other example values that look real can still match. High-entropy strings are reported at Low severity and low confidence; identifiers such as content hashes trigger them. Secrets in a stdio server's environment are expected (the spec says stdio servers take credentials from the environment) and are reported as Low so the operator can confirm least privilege.

Fix: Remove secrets from descriptions and resources, rotate anything that was exposed, and pass credentials through the environment or a secret store, never through metadata.

passivehttp, stdioHighMCP01:2025 (beta) · LLM02:2026 · LLM02:2025Pending
META-06Tool annotations missing or inconsistent with the toolReads each tool's annotations from tools/list.
Details and fix

Reads each tool's annotations from tools/list. Reported as missing: readOnlyHint, openWorldHint and a title (tool.title or annotations.title) on every tool, and destructiveHint and idempotentHint on every tool not marked readOnlyHint:true (the spec says those two are meaningful only when readOnlyHint is false). Reported as inconsistent: readOnlyHint:true on a tool that looks like it executes, writes, deletes, sends or pays; destructiveHint:false on a tool that looks like it executes, deletes or overwrites; openWorldHint:false on a tool that reaches the network; a hint that is not a boolean; and, as low-severity noise, destructiveHint:true on a tool that only appears to read. Medium when a dangerous-class tool is mislabelled, low when annotations are merely missing. One finding lists every affected tool. Anthropic's directory policy (5E) and OpenAI's app review both require accurate annotations.

Evidence: The tools/list response; each affected tool's name, title and annotations are shown as proof.

False positives: The capability behind a contradiction is inferred from keywords in the tool's name, description and parameter names, so a narrowly scoped tool (for example 'delete_draft' that only removes the caller's own draft) may be misread. Missing annotations are a plain observation. Annotations are hints that clients must treat as untrusted; correcting them does not change what a tool can do.

Fix: Give every tool a title and set readOnlyHint and openWorldHint explicitly; for tools that are not read-only also set destructiveHint and idempotentHint. Make each value true to the implementation: readOnlyHint:true only when nothing is modified, destructiveHint:true for anything that executes, deletes or overwrites, openWorldHint:true for tools that reach the internet or other external systems. Anthropic's Software Directory Policy (5E, https://support.claude.com/en/articles/13145358-anthropic-software-directory-policy) requires all applicable annotations, and OpenAI's app review (https://developers.openai.com/plugins/deploy/app-review.md) checks readOnlyHint, destructiveHint and openWorldHint for accuracy.

passivehttp, stdioMediumMCP spec conformance / hygiene (no OWASP item)Pending
META-07Toxic flow: private data, untrusted content and external send on one serverClassifies every advertised tool into three roles from its capability class and wording: access to private data (files, databases, credentials, the user's mail), intake of untrusted content (fetching URLs, web search, reading mail or messages written by others) and a way to send data out (sending e-mail or messages, HTTP posts, webhooks, uploads).
Details and fix

Classifies every advertised tool into three roles from its capability class and wording: access to private data (files, databases, credentials, the user's mail), intake of untrusted content (fetching URLs, web search, reading mail or messages written by others) and a way to send data out (sending e-mail or messages, HTTP posts, webhooks, uploads). A tool advertising arbitrary command execution counts for all three; arbitrary file read counts as private data. When one server offers all three roles, text planted in the untrusted content can instruct the model to read the private data and send it away: the 'lethal trifecta' of prompt injection. Medium, high when the HTTP endpoint needs no authentication. One finding lists the tools in each role. No tool is called.

Evidence: The tools/list response; each role lists its tools and the wording that put them there.

False positives: Roles are inferred from names, descriptions and capability keywords, not from behaviour. A 'fetch' tool restricted to one internal API, or a 'send' tool that only notifies the signed-in user, is still counted. Conversely a fetch tool with a free-form URL can leak data through the URL itself; that path is not counted as a send role.

Fix: Break the trifecta: split the tools across separate servers (or separate client configurations) so no single agent session combines private data, untrusted content and an outbound channel; or gate the send tool behind explicit per-call user confirmation and an allow-list of destinations; or constrain the intake tool to trusted sources. Keep the server authenticated so nobody else can drive the combination.

passivehttp, stdioMediumASI01 · LLM01:2026 · LLM01:2025Pending

Robustness

ERR-01 · DOS-01

Verbose errors, and three bounded probes for size, nesting and rate limits. Never more than one oversized request, one deep request and 20 paced list calls.

Robustness checks with probe, mode, default severity, framework mapping and false-positive rate
IDCheckWhat it doesModeSeverityMaps toFP rate
ERR-01Verbose error responses leak stack traces, paths or versionsSends three malformed requests: truncated JSON, an unknown method and a request whose params is a string instead of an object.
Details and fix

Sends three malformed requests: truncated JSON, an unknown method and a request whose params is a string instead of an object. Error bodies and the Server header are inspected for stack traces, internal file paths and framework version strings.

Evidence: Each malformed request and the error response body.

False positives: A Server header with a version is reported as Info. Framework names without versions are not reported.

Fix: Return generic JSON-RPC errors (-32700/-32600/-32601/-32602) without 'data' containing exceptions, log details server-side, and strip the Server header version at the proxy.

passivehttp, stdioMediumMCP08:2025 (beta) · LLM02:2026 · LLM02:2025Pending
DOS-01No visible limits on request size, nesting or rateThree bounded probes, never more: (1) one tools/list whose 'cursor' is a 1 MB string, (2) one tools/list with params nested 64 levels deep, (3) 20 tools/list requests sent at the scan rate cap (5 req/s by default).
Details and fix

Three bounded probes, never more: (1) one tools/list whose 'cursor' is a 1 MB string, (2) one tools/list with params nested 64 levels deep, (3) 20 tools/list requests sent at the scan rate cap (5 req/s by default). A 5xx, a transport failure or a response slower than 5 s on (1)/(2) is reported; absence of any 429 during (3) is reported as informational. No tools are called.

Evidence: The oversized/nested requests (truncated) and timing; the burst responses' statuses.

False positives: The burst runs inside the scanner's own rate cap, so 'no 429 observed' is indicative only (low confidence) and many well-run servers legitimately allow 5 req/s. A 413 or connection reset on the oversized probe is treated as a correct defence.

Fix: Enforce a request body limit (e.g. 1 MB) and JSON depth limit at the edge, return 413/400 promptly, and rate-limit per client/session with 429 and Retry-After.

passivehttp, stdioLowASI08 · LLM06:2026 · LLM10:2025Pending

Injection (active, coming soon)

INJ-01 … INJ-05

Registered in v0.1.0 behind the authorisation gate and reported as not implemented. No payloads are sent yet.

Injection (active, coming soon) checks with probe, mode, default severity, framework mapping and false-positive rate
IDCheckWhat it doesModeSeverityMaps toFP rate
INJ-01Command/code injection (safe canaries)Will call exec-class tools with time-based, non-destructive canaries and compare response timing.
Details and fix

Will call exec-class tools with time-based, non-destructive canaries and compare response timing. requires --active and verified ownership.

Evidence: tools/call request with the canary and the timed response.

False positives: Network jitter can mimic a timing delta; the probe will repeat and require consistency.

Fix: Never pass tool arguments to a shell; use argument vectors and allow-lists.

active · coming soonhttp, stdioCriticalMCP05:2025 (beta) · ASI05 · LLM10:2026n/a
INJ-02Path traversal / arbitrary file readRead-only traversal probes on path-typed arguments.
Details and fix

Read-only traversal probes on path-typed arguments. requires --active and verified ownership.

Evidence: tools/call request with the traversal path and the response excerpt.

False positives: Tools that intentionally expose the whole filesystem are a design decision, not a bug.

Fix: Canonicalise paths, resolve symlinks, and enforce a root directory check after resolution.

active · coming soonhttp, stdioHighMCP05:2025 (beta) · ASI02n/a
INJ-03Server-side request forgeryCallback-based SSRF probes on URL-typed arguments.
Details and fix

Callback-based SSRF probes on URL-typed arguments. requires --active and verified ownership.

Evidence: tools/call request with the callback URL and the callback log entry.

False positives: Fetch tools are often meant to fetch arbitrary URLs; the finding focuses on internal/metadata addresses.

Fix: Resolve and validate destination addresses, block link-local and private ranges, use an egress proxy.

active · coming soonhttp, stdioHighMCP05:2025 (beta) · ASI02n/a
INJ-04SQL injection (safe markers)Boolean and timing markers on query/filter arguments, plus error fingerprinting.
Details and fix

Boolean and timing markers on query/filter arguments, plus error fingerprinting. requires --active and verified ownership.

Evidence: tools/call requests and differential responses.

False positives: Tools that accept raw SQL by design are reported as a capability (META-03), not an injection.

Fix: Use parameterised queries; never interpolate tool arguments into SQL.

active · coming soonhttp, stdioHighMCP05:2025 (beta)n/a
INJ-05Tool output returned without sanitisation (contextual payload path)Read-only tool calls against scanner-controlled canary content.
Details and fix

Read-only tool calls against scanner-controlled canary content. requires --active and verified ownership.

Evidence: tools/call request and the returned content.

False positives: Returning fetched content verbatim is normal; the finding documents the path for the client's risk assessment.

Fix: Mark tool output as untrusted data in content blocks and strip instruction-like markup where feasible.

active · coming soonhttp, stdioMediumMCP06:2025 (beta) · MCP10:2025 (beta) · ASI06 · LLM01:2026 · LLM01:2025n/a

Supply chain and sandbox (active, coming soon)

SUPPLY-01 … SANDBOX-01

For stdio packages and client configs. Registered in v0.1.0 and reported as not implemented.

Supply chain and sandbox (active, coming soon) checks with probe, mode, default severity, framework mapping and false-positive rate
IDCheckWhat it doesModeSeverityMaps toFP rate
SUPPLY-01Package provenance and known vulnerabilities (stdio)Registry metadata, OSV lookup and install-script review for the stdio package.
Details and fix

Registry metadata, OSV lookup and install-script review for the stdio package. requires --active and verified ownership.

Evidence: Registry metadata documents and OSV responses.

False positives: Unpinned versions are common in examples; severity will depend on install-script presence.

Fix: Pin versions, commit lockfiles, publish with provenance attestations, avoid install scripts.

active · coming soonstdioMediumMCP04:2025 (beta) · ASI04 · LLM04:2026 · LLM03:2025n/a
SUPPLY-02stdio configuration launches risky commandsStatic review of a submitted client configuration file.
Details and fix

Static review of a submitted client configuration file. requires --active and verified ownership.

Evidence: The configuration entry.

False positives: npx -y with a pinned version is acceptable; unpinned is flagged.

Fix: Pin packages, avoid shell wrappers, keep secrets out of config files.

active · coming soonstdioHighMCP05:2025 (beta) · MCP04:2025 (beta) · ASI05n/a
SANDBOX-01Unexpected runtime behaviour during listing (stdio)Sandboxed execution with egress and syscall logging.
Details and fix

Sandboxed execution with egress and syscall logging. requires --active and verified ownership.

Evidence: Sandbox egress/file/process log.

False positives: Telemetry and update checks are common; the finding will list hosts for review.

Fix: Do not contact the network or touch files outside the package during start-up and listing.

active · coming soonstdioHighMCP04:2025 (beta) · ASI10 · ASI04n/a

Attestation only

GOV-01 … GOV-05

Cannot be assessed by a black-box scan. Every report lists them with a checklist and never marks them passed or failed.

Attestation only checks with probe, mode, default severity, framework mapping and false-positive rate
IDCheckWhat it doesModeSeverityMaps toFP rate
GOV-01Audit logging and telemetry for tool invocationsWhether a server logs and alerts on tool calls is not observable from outside.
Details and fix

Whether a server logs and alerts on tool calls is not observable from outside.

  • Every tools/call is logged with caller identity, tool name, arguments digest and outcome.
  • Logs are shipped off-host, retained, and reviewed or alerted on.
  • Authentication failures and authorisation denials are logged.
attestationn/aMCP08:2025 (beta)n/a
GOV-02Shadow MCP servers (inventory of servers in use)An inventory problem across workstations and repositories, not an endpoint property.
Details and fix

An inventory problem across workstations and repositories, not an endpoint property.

  • Maintain an inventory of approved MCP servers and their owners.
  • Periodically review client configuration files (mcp.json and similar) for unapproved entries.
attestationn/aMCP09:2025 (beta)n/a
GOV-03Data and model poisoning in training or fine-tuning pipelinesTraining-pipeline integrity is not black-box testable.
Details and fix

Training-pipeline integrity is not black-box testable.

  • Training and retrieval data sources are provenance-tracked and access-controlled.
  • Data changes are reviewed before they reach a model or index.
attestationn/aLLM05:2026 · LLM04:2025n/a
GOV-04Inter-agent communication, cascading failures, human trust, rogue agentsArchitecture and process items; multi-agent paths are not externally visible.
Details and fix

Architecture and process items; multi-agent paths are not externally visible.

  • Agent-to-agent channels are authenticated (the AUTH checks apply to any exposed endpoint).
  • Failure of one tool or agent is contained (timeouts, circuit breakers, budgets).
  • High-impact actions require explicit human approval with the full action shown.
  • Agents can be stopped centrally and their credentials revoked.
attestationn/aASI07 · ASI08 · ASI09 · ASI10n/a
GOV-05Memory and context poisoning persistenceNeeds a customer-supplied test session across two conversations; not a server-side scan.
Details and fix

Needs a customer-supplied test session across two conversations; not a server-side scan.

  • Persistent memory is scoped per user and per tenant.
  • Stored memories can be reviewed and deleted by the user.
  • Content from tool output is not written to long-term memory without review.
attestationn/aASI06n/a

False-positive rates are measured against the public “state of MCP server security” dataset and published per check once there are at least 100 samples. Until then the column reads “Pending”.

Read the methodology