Checks catalogue · v0.1
Every check, what it probes, and how often it is wrong.
29 catalogue entries, generated from the scanner itself (mcpprobe 0.1.0) and mapped to OWASP MCP Top 10 (beta), Agentic Top 10 and LLM Top 10 (2026 and 2025). The 16 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 29 of 29 checks
Authentication
AUTH-01 … AUTH-04Unauthenticated endpoints, RFC 9728 protected-resource metadata, PKCE S256 and HTTPS on the authorization server, and tokens with the wrong audience or issuer.
| ID | Check | What it does | Mode | Severity | Maps to | FP rate |
|---|---|---|---|---|---|---|
| AUTH-01 | Remote MCP endpoint accepts requests without authentication | POSTs initialize (or server/discover) and tools/list with no Authorization header.Details and fixPOSTs 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. Missing authentication was the single most common issue in public MCP server studies. Evidence: The unauthenticated tools/list request and the 200 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 pointing at RFC 9728 protected-resource metadata, validate token audience, and reject requests without a valid bearer token. For local servers, bind to 127.0.0.1 and still require a token. | passivehttp | High | MCP07:2025 (beta) · ASI03 · LLM04:2026 · LLM03:2026 · LLM03:2025 · LLM06:2025 | Pending |
| AUTH-02 | Protected resource metadata (RFC 9728) missing or invalid | On a 401 the scanner parses WWW-Authenticate for resource_metadata, then tries /.well-known/oauth-protected-resource[/path] and the host root.Details and fixOn a 401 the scanner parses WWW-Authenticate for resource_metadata, 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. Evidence: The 401 response headers and each metadata GET with its status/body. 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. 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. | passivehttp | High | MCP07:2025 (beta) | Pending |
| AUTH-03 | Authorization 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 fixFor 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. | passivehttp | High | MCP07:2025 (beta) · MCP01:2025 (beta) | Pending |
| AUTH-04 | Server accepts a self-minted token with the wrong audience/issuer | 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.Details and fixMints 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. | passivehttp | Critical | MCP07:2025 (beta) · MCP01:2025 (beta) · ASI03 | Pending |
Transport
TRANS-01 … TRANS-05Origin validation (DNS rebinding), protocol-version handling, session-id quality and forgery, deprecated HTTP+SSE, TLS and security headers.
| ID | Check | What it does | Mode | Severity | Maps to | FP rate |
|---|---|---|---|---|---|---|
| TRANS-01 | Origin header not validated (DNS-rebinding exposure) | Sends a normal negotiation request with 'Origin: https://evil.example'.Details and fixSends a normal negotiation request with 'Origin: https://evil.example'. The transport spec says servers MUST validate Origin and return 403 on an invalid one; otherwise a web page can drive a locally running MCP server through the victim's browser (DNS rebinding). Evidence: The POST with the foreign Origin header and the non-403 response. False positives: If the server answers 401 before looking at Origin the check is indeterminate and no finding is raised (see scan notes). Reverse proxies that strip Origin will cause a finding against the proxied endpoint even if the application validates it. Fix: Reject requests whose Origin is not on an allow-list with HTTP 403 before processing the body. For local servers also bind to 127.0.0.1 rather than 0.0.0.0. | passivehttp | Medium | MCP07:2025 (beta) | Pending |
| TRANS-02 | Unsupported MCP-Protocol-Version header not rejected | Sends a request with 'MCP-Protocol-Version: 1999-01-01'.Details and fixSends 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. Fix: Validate MCP-Protocol-Version against the supported list and reply 400 when it is unknown. | passivehttp | Low | MCP spec conformance / hygiene (no OWASP item) | Pending |
| TRANS-03 | Weak, predictable or unvalidated Mcp-Session-Id | Collects three session IDs from repeated initialize requests and checks length, character set, Shannon entropy and sequentiality.Details and fixCollects 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. | passivehttp | High | MCP07:2025 (beta) | Pending |
| TRANS-04 | Deprecated HTTP+SSE (2024-11-05) transport in use | Reports when the endpoint answers a GET with an SSE 'endpoint' event, i.e.Details and fixReports 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. | passivehttp | Info | MCP spec conformance / hygiene (no OWASP item) | Pending |
| TRANS-05 | Plain HTTP, weak TLS or missing security headers | 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.Details and fixFlags 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. | passivehttp | High | MCP01:2025 (beta) | Pending |
Tool metadata
META-01 … META-05Tool-description poisoning, rug-pull diffs against a stored baseline, annotations that contradict capability, schema hygiene and secrets in metadata.
| ID | Check | What it does | Mode | Severity | Maps to | FP rate |
|---|---|---|---|---|---|---|
| META-01 | Possible tool-description poisoning | Scans every tool, prompt and resource description, every inputSchema parameter description and the server 'instructions' for: prompt-style markup (<IMPORTANT>, <system>), instructions aimed at the model (conceal from user, override instructions, read-and-forward, prerequisite coercion, redirect/replace), credential file paths, references to other tools with behaviour-modifying language (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 fixScans every tool, prompt and resource description, every inputSchema parameter description and the server 'instructions' for: prompt-style markup (<IMPORTANT>, <system>), instructions aimed at the model (conceal from user, override instructions, read-and-forward, prerequisite coercion, redirect/replace), credential file paths, references to other tools with behaviour-modifying language (shadowing), URLs and e-mail addresses with send/BCC wording, base64 blobs, zero-width/bidi/tag Unicode, mixed-script homoglyphs and excessive length. Findings carry tiered confidence and are never rated Critical on heuristics alone. Evidence: The tools/list (or prompts/resources/initialize) response and the matched excerpts. False positives: Legitimate guidance such as 'IMPORTANT: call authenticate before this tool' matches the markup and prerequisite heuristics at medium confidence. URLs to documentation and mentions of sibling tools without behaviour-modifying words are reported at low severity. 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: Remove any text addressed to the model rather than describing the tool. Keep descriptions short and factual, strip invisible Unicode, and never reference other servers' tools. Pin and hash approved descriptions in clients (see META-02). | passivehttp, stdio | High | MCP03:2025 (beta) · ASI01 · ASI04 · LLM01:2026 · LLM01:2025 | Pending |
| META-02 | Tool 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 fixComputes 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, stdio | Medium | MCP03:2025 (beta) · ASI04 | n/a (diff) |
| META-03 | Tool annotations contradict the tool's apparent capability | Classifies each tool by name, description and parameter names into capability classes (exec, file_write, file_read, database_*, network, email, credentials, payments, delete, search) and cross-checks the declared annotations: a tool that looks like it runs commands or sends e-mail but is marked readOnlyHint:true, or an exec/delete tool marked destructiveHint:false, is reported.Details and fixClassifies each tool by name, description and parameter names into capability classes (exec, file_write, file_read, database_*, network, email, credentials, payments, delete, search) and cross-checks the declared annotations: a tool that looks like it runs commands or sends e-mail but is marked readOnlyHint:true, or an exec/delete tool marked destructiveHint:false, is reported. A summary of the dangerous surface is reported at low severity. Annotations are treated as untrusted hints, as the spec requires of clients. Evidence: The tools/list response; matched terms per tool are listed in details. False positives: Classification is keyword-based: a tool named 'delete_draft' that only removes the user's own draft will be classed 'delete'. Confidence is medium for contradictions and the dangerous-surface summary is informational. Fix: Make annotations truthful (readOnlyHint only for tools with no side effects, destructiveHint:true for anything that deletes or executes), and consider splitting broad tools into narrower ones so clients can gate approval. | passivehttp, stdio | Medium | MCP02:2025 (beta) · MCP05:2025 (beta) · ASI02 · ASI05 · LLM03:2026 · LLM06:2025 | Pending |
| META-04 | Tool schema hygiene problems | 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.Details and fixChecks 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. Missing outputSchema cannot be judged without calling the tool and is not reported. Evidence: The tools/list response. 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: Use valid names, give every tool an object inputSchema, and constrain risky string arguments with enum/pattern/format/maxLength so clients and servers can validate. | passivehttp, stdio | Low | MCP05:2025 (beta) | Pending |
| META-05 | Secret material in server metadata or configuration | 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.Details and fixPattern 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: Example keys from vendor documentation (for instance the AWS sample key IDs ending in EXAMPLE) match the patterns. 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, stdio | High | MCP01:2025 (beta) · LLM02:2026 · LLM02:2025 | Pending |
Robustness
ERR-01 · DOS-01Verbose 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.
| ID | Check | What it does | Mode | Severity | Maps to | FP rate |
|---|---|---|---|---|---|---|
| ERR-01 | Verbose error responses leak stack traces, paths or versions | Sends three malformed requests: truncated JSON, an unknown method and a request whose params is a string instead of an object.Details and fixSends 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, stdio | Medium | MCP08:2025 (beta) · LLM02:2026 · LLM02:2025 | Pending |
| DOS-01 | No visible limits on request size, nesting or rate | 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).Details and fixThree 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, stdio | Low | ASI08 · LLM06:2026 · LLM10:2025 | Pending |
Injection (active, coming soon)
INJ-01 … INJ-05Registered in v0.1.0 behind the authorisation gate and reported as not implemented. No payloads are sent yet.
| ID | Check | What it does | Mode | Severity | Maps to | FP rate |
|---|---|---|---|---|---|---|
| INJ-01 | Command/code injection (safe canaries) | Will call exec-class tools with time-based, non-destructive canaries and compare response timing.Details and fixWill 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, stdio | Critical | MCP05:2025 (beta) · ASI05 · LLM10:2026 | n/a |
| INJ-02 | Path traversal / arbitrary file read | Read-only traversal probes on path-typed arguments.Details and fixRead-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, stdio | High | MCP05:2025 (beta) · ASI02 | n/a |
| INJ-03 | Server-side request forgery | Callback-based SSRF probes on URL-typed arguments.Details and fixCallback-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, stdio | High | MCP05:2025 (beta) · ASI02 | n/a |
| INJ-04 | SQL injection (safe markers) | Boolean and timing markers on query/filter arguments, plus error fingerprinting.Details and fixBoolean 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, stdio | High | MCP05:2025 (beta) | n/a |
| INJ-05 | Tool output returned without sanitisation (contextual payload path) | Read-only tool calls against scanner-controlled canary content.Details and fixRead-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, stdio | Medium | MCP06:2025 (beta) · MCP10:2025 (beta) · ASI06 · LLM01:2026 · LLM01:2025 | n/a |
Supply chain and sandbox (active, coming soon)
SUPPLY-01 … SANDBOX-01For stdio packages and client configs. Registered in v0.1.0 and reported as not implemented.
| ID | Check | What it does | Mode | Severity | Maps to | FP rate |
|---|---|---|---|---|---|---|
| SUPPLY-01 | Package provenance and known vulnerabilities (stdio) | Registry metadata, OSV lookup and install-script review for the stdio package.Details and fixRegistry 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 soonstdio | Medium | MCP04:2025 (beta) · ASI04 · LLM04:2026 · LLM03:2025 | n/a |
| SUPPLY-02 | stdio configuration launches risky commands | Static review of a submitted client configuration file.Details and fixStatic 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 soonstdio | High | MCP05:2025 (beta) · MCP04:2025 (beta) · ASI05 | n/a |
| SANDBOX-01 | Unexpected runtime behaviour during listing (stdio) | Sandboxed execution with egress and syscall logging.Details and fixSandboxed 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 soonstdio | High | MCP04:2025 (beta) · ASI10 · ASI04 | n/a |
Attestation only
GOV-01 … GOV-05Cannot be assessed by a black-box scan. Every report lists them with a checklist and never marks them passed or failed.
| ID | Check | What it does | Mode | Severity | Maps to | FP rate |
|---|---|---|---|---|---|---|
| GOV-01 | Audit logging and telemetry for tool invocations | Whether a server logs and alerts on tool calls is not observable from outside.Details and fixWhether a server logs and alerts on tool calls is not observable from outside.
| attestation | n/a | MCP08:2025 (beta) | n/a |
| GOV-02 | Shadow MCP servers (inventory of servers in use) | An inventory problem across workstations and repositories, not an endpoint property.Details and fixAn inventory problem across workstations and repositories, not an endpoint property.
| attestation | n/a | MCP09:2025 (beta) | n/a |
| GOV-03 | Data and model poisoning in training or fine-tuning pipelines | Training-pipeline integrity is not black-box testable.Details and fixTraining-pipeline integrity is not black-box testable.
| attestation | n/a | LLM05:2026 · LLM04:2025 | n/a |
| GOV-04 | Inter-agent communication, cascading failures, human trust, rogue agents | Architecture and process items; multi-agent paths are not externally visible.Details and fixArchitecture and process items; multi-agent paths are not externally visible.
| attestation | n/a | ASI07 · ASI08 · ASI09 · ASI10 | n/a |
| GOV-05 | Memory and context poisoning persistence | Needs a customer-supplied test session across two conversations; not a server-side scan.Details and fixNeeds a customer-supplied test session across two conversations; not a server-side scan.
| attestation | n/a | ASI06 | n/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