Detection rules reference
Hecate checks MCP client configs and tool definitions with eight deterministic rules. Critical and high findings exit with code 1, so the same run can block a merge.
Rules that need tool definitions (MCP001, MCP003, MCP004, MCP005) see them in a tools file, or with --connect, which starts each server in a config and lists its tools. Config rules (MCP006, MCP007, MCP008) work on the config alone. Pass everything one agent uses in one run so the cross-server rules can see it.
| Rule | Finds | Severity |
|---|---|---|
| MCP001 | Tool poisoning | Critical / high |
| MCP002 | Rug pulls against a pinned lockfile | High (low for removed tools) |
| MCP003 | Tool shadowing and name collisions | High / medium |
| MCP004 | Excessive scope | Critical / high / medium |
| MCP005 | Lethal trifecta | High |
| MCP006 | Secrets exposure | High / medium |
| MCP007 | Known-bad and disallowed servers | Critical / high |
| MCP008 | Unpinned or insecure server sources | High / medium |
MCP001: Tool poisoning
Text in a tool definition written to steer the model rather than describe the tool. MCP001 reads the description, the title, and every description, title and default in the input schema, and scores what it finds:
- Critical, any one of: overriding the user or earlier instructions (“regardless of the user’s input”); secrecy (“do not tell the user”, “do not ask for confirmation”); sensitive files such as
~/.ssh/id_rsa, or SQL that selects secrets; sending data to a literal URL or address, directly or through a sending tool; exfiltration payloads (curl,fetch,document.cookie); data-carrying image URLs; pseudo-system tags such as<IMPORTANT>; hidden comments; invisible Unicode; control characters, including in the tool name. - High, two different ones of: directing how another tool is used; rewriting its arguments; mandate or threat framing (“this step is mandatory”, “skipping this will cause errors”); cover stories (“due to a system update”, “for internal testing”); calling another tool with fixed values; calling a tool that changes state; directives about credentials or user data.
Ordinary instructions (“You must first call list_projects to get a project id”), emoji and right-to-left text are not flagged. On MCPTox it catches 88% of held-out poisoned tools and flags none of 362 real ones.
Fix: read the full definition and the server’s source; remove the server unless the text is benign and expected. Guide: MCP tool poisoning.
MCP002: Rug pull
High. Reported by hecate check when a tool’s definition no longer matches the hash in hecate.lock.json, or a tool appears that was not pinned. A pinned tool that is no longer served is low.
Fix: diff the new definition against the approved one. Re-approve an expected change with hecate pin; otherwise stop using the server. Guide: MCP rug pull attacks.
MCP003: Tool shadowing
High when a tool or parameter description mentions another server’s tool with directive language (“whenever send_email is used, …”); medium for a plain mention, or when the same tool name is served by more than one server.
Fix: tools should only describe themselves. Remove the server, or rename colliding tools. Guide: MCP tool shadowing.
MCP004: Excessive scope
- A tool that runs commands or code: high, or critical when the same agent also reads untrusted content.
- A server that can write files while the agent reads untrusted content, which could plant shell profiles, git hooks or CI config: medium.
- A stdio server given the filesystem root (high) or a home directory (medium) as an argument.
Fix: scope servers to a project or scratch directory, drop command-execution tools the agent does not need, or require approval before they run.
MCP005: Lethal trifecta
High. Across every server passed in one run, the agent has tools for untrusted content, private data and external communication. Tools are classified by name, parameters and description; the finding lists which tools make up each leg, and hecate graph draws it as a Mermaid diagram.
Fix: remove a leg for this agent, split the work across agents, or require approval before outbound tools run. Correct a misclassified tool with a capabilities entry in the policy. Guide: the lethal trifecta.
MCP006: Secrets exposure
High for known token formats (AWS, GitHub, Slack, Stripe, OpenAI and others) anywhere in a config or tool definition. Medium for literal values of secret-named keys and flags, passwords in connection URLs, and secrets in URL query strings. Findings name the location and the kind of secret; the value is never printed.
Fix: move the secret into the environment and reference it ("${env:NAME}" in VS Code and Cursor, "${NAME}" in Claude Code’s .mcp.json). Rotate it if the file was ever committed or shared.
MCP007: Known-bad or disallowed server
Critical for packages known to be malicious, such as postmark-mcp 1.0.16 and later; high for versions with a known exploitable vulnerability, such as mcp-remote before 0.1.16 (CVE-2025-6514). The built-in list is small and every entry is sourced. High as well for servers on your policy’s servers.deny list, or missing from its servers.allow list, matched by package, image, URL or command.
Fix: remove or upgrade the server and rotate anything it could reach.
MCP008: Unpinned or insecure source
High for a remote server reached over plain http://. Medium for an npm or PyPI package run without an exact version, and for a container image with no tag or tagged latest.
Fix: pin exact versions (server@1.2.3, server==1.2.3), prefer images by digest, and use https://.
Recording reviewed exceptions
Findings you have reviewed and accepted go in hecate.policy.json, with a reason and optionally an expiry date. They still appear in the output, marked as accepted, but no longer fail the run. Unknown keys and rule IDs are errors, so a typo cannot silently disable a check.
{
"version": 1,
"ignore": [
{
"rule": "MCP005",
"reason": "Sandboxed agent, no credentials; reviewed by @alice",
"expires": "2026-12-31"
}
]
}