When an MCP client asks you to approve a server, what is the thing you are approving?
If the answer is only filesystem, github, or run_command, the answer is too loose. A tool name is a label. It does not tell you which command will run, which arguments it accepts, which environment it inherits, or which tool definition the model will read.
That gap matters because an MCP server can keep the same name while changing the content behind it. The name stays familiar. The consent should not.
Short answer
Field rule: bind approval to a canonical content hash of the executable configuration and tool definition—not to the tool name. If the hash changes, treat it as a new consent event and ask again.
This is not a claim that hashing solves tool poisoning. It solves a narrower problem: silent drift after approval. The user gets a fresh decision point when the thing being trusted is no longer the thing that was reviewed.
Rug pulls: the approved name is not the approved behavior
Invariant Labs describes an MCP rug pull as a server changing a tool description after the user has approved it. The changed description can add instructions that the model sees even when the user-facing interface shows only a simplified tool summary. Invariant’s mitigation guidance includes pinning tools and packages with a hash or checksum. [1]
That is the practical distinction:
- Name approval: “I approved
search.” - Content approval: “I approved this server, this tool description, this input schema, this command, these arguments, and this environment, identified by this digest.”
The first can remain green while the second changes underneath it. A long-lived approval that keys only on the name is therefore not lasting control. It is a remembered label.
MCPoison: a concrete sequence
CVE-2025-54136, called MCPoison by Check Point Research, gives this problem a concrete shape. The reported sequence for Cursor versions through 1.2.4 was:
- An attacker adds a benign
.cursor/mcp.jsonto a shared repository. - A developer opens the repository and approves the apparently safe MCP configuration.
- The attacker later replaces the configuration with a malicious payload.
- The client trusts the previously approved configuration without asking again.
The vulnerable behavior was indefinite trust in a previously approved MCP configuration. The reported impact was persistent remote code execution. The reported CVSS range is approximately 7.2–8.8. The issue was fixed in Cursor 1.3, which requires re-approval when the configuration changes, including a whitespace change. [2]
The lesson is not “always reject MCP.” It is “approval must follow the bytes and definitions that approval covered.” If a one-character change can matter to the client’s trust decision, the trust record needs a precise representation of what changed.
NVD tracks the issue as CVE-2025-54136. [3]
Field rule: store the content, enforce the mismatch
For every approved MCP integration, store a consent record containing at least:
- the server or package identity;
- the canonical content covered by approval;
- the resulting cryptographic digest;
- the approving principal and timestamp;
- the client or policy version that evaluated it; and
- the scope of allowed use.
At invocation or configuration load, recompute the digest from the content that will actually be used. Compare it with the approved digest.
Hash match: continue under the existing policy.
Hash mismatch: stop, mark the approval stale, show the diff or changed fields, and request a new consent event.
Do not silently update the stored hash after a mismatch. That converts detection into acceptance. Do not treat a changed description as cosmetic. A description is part of the model-visible behavior surface, even when it is not executable code.
Keep reading with free field-guide resources.
VibeSec Advisory publishes practical research, Skills, MCP notes, prompt injection tests, and AI red-team lessons for builders working with agentic AI.
The Cloud Security Alliance notes that MCP has no native defenses against rug pulls and recommends pinning versions and alerting on tool-definition changes. [4] A client or policy layer has to supply that missing control.
What belongs in the hash?
The exact material depends on the integration. The goal is to hash the content that can change what the agent does or what the server can reach.
For a local or STDIO server, include a canonical representation of:
- executable command and interpreter;
- ordered arguments;
- working directory;
- environment variable names and values, or a safe reference to secret material;
- configuration-file contents or content digests;
- server package and version identity; and
- transport and endpoint settings.
For a remote MCP server, include a canonical tool manifest:
- server identity and endpoint;
- tool names;
- descriptions, including model-visible text;
- input schemas and defaults;
- annotations or declared side effects;
- server and package version information; and
- the manifest’s retrieval or signing metadata, where available.
Canonicalization is part of the control. Use stable field ordering, explicit encoding, and an unambiguous representation of absent versus empty values. Hash the effective values, not merely the path to a file. If a secret must not be stored in the consent record, hash a stable secret reference or version identifier and keep the secret itself out of the record.
This is a field design recommendation, not a claim that MCP currently standardizes one universal hash format. The important property is reproducibility: the client and the consent recorder must hash the same effective content.
What the consent event UI should show
A useful re-approval prompt should answer “what changed?” without requiring the operator to decode a digest.
Show:
- the server identity and trust scope;
- the old and new content digests, with a copyable full value;
- a readable diff of changed commands, arguments, environment entries, endpoints, tool descriptions, schemas, and versions;
- newly added or removed tools;
- declared capabilities and side effects; and
- the consequence of approval, including whether the change expands access.
Keep the hash as the stable audit key. Keep the diff as the human decision aid. A green “same tool name” indicator is not an adequate substitute for either.
Sandbox tests: six cases
Use these as small acceptance tests for an MCP client, wrapper, or policy layer:
- Argument change: approve
server --port 8080; change the port to8081. The digest must change and approval must be requested again. - Environment change: approve an integration with one allowed environment entry; add or change an entry. The digest must change. Secret values must not appear in the UI or record.
- Description change: alter only model-visible tool text. The digest must change and the client must not dismiss it as non-executable metadata.
- Schema change: add a required parameter, widen an enum, or change a default. The digest must change and the diff must identify the field.
- Whitespace change: modify formatting in the effective configuration. The canonicalization policy must make the result predictable; if formatting is semantically preserved, explain that in the record. If the client treats raw config changes as security-relevant, re-prompt consistently.
- Tool-set change: add, remove, or rename a tool while keeping the server name constant. The manifest digest must change and the prompt must identify the capability delta.
The test is not only whether a hash changes. It is whether the client blocks the old consent from silently covering the new content.
Fit with consent-record and authorization posts
This is the same boundary used in a good MCP consent record: record what was authorized, by whom, under which scope, and against which exact content. The digest makes “what” machine-checkable.
It also keeps permission separate from identity. A trusted server identity can tell you who supplied a configuration. It does not prove that today’s command, arguments, environment, or tool manifest are the same ones the operator approved. Identity and approval are related fields, not interchangeable keys.
For local STDIO installs, pair this with the STDIO install record: hash the command, args, and env you recorded before launch, then re-check on every start. For description and rug-pull cases covered in the MCP tool-poisoning lab, the hash is the control that forces re-consent when the model-visible text changes after the first green approval.
The pattern fits least privilege, too. A hash mismatch should not widen a standing grant just because the server name is unchanged. Re-approval is the point where a reviewer can reject a new endpoint, a new environment value, an extra tool, or a broader schema.
A content-bound approval is not a substitute for sandboxing, capability limits, tool-output review, or runtime monitoring. It is the control that prevents yesterday’s approval from being silently reused for today’s content.
Evidence versus opinion
Evidence: Invariant Labs documented tool poisoning and rug pulls, and recommended tool or package pinning with a hash or checksum. [1]
Evidence: The MCPoison description reports that Cursor versions through 1.2.4 trusted an approved MCP configuration after modification, and that Cursor 1.3 added re-approval for configuration changes, including whitespace changes. [2]
Evidence: NVD records CVE-2025-54136. [3]
Evidence: The Cloud Security Alliance says the protocol lacks native rug-pull defenses and recommends version pinning and alerts on tool-definition changes. [4]
Opinion / field rule: represent the effective MCP command, arguments, environment, or tool manifest with a canonical digest; treat any digest mismatch as a new consent event; show a readable diff before approval.
That last paragraph is the proposed control design. It is deliberately narrower than “trust hashes.” Hashes identify drift. Policy, review, and isolation determine whether the new content is acceptable.
Sources
- Invariant Labs, “MCP Security Notification: Tool Poisoning Attacks” — https://invariantlabs.ai/blog/mcp-security-notification-tool-poisoning-attacks
- The Vulnerable MCP Project, “Cursor MCP Definition Bypass / MCPoison (CVE-2025-54136)” — https://vulnerablemcp.info/vuln/cve-2025-54136-cursor-mcpoison.html
- NIST National Vulnerability Database, “CVE-2025-54136 Detail” — https://nvd.nist.gov/vuln/detail/CVE-2025-54136
- Cloud Security Alliance, “MCP Security Crisis: Systemic Design Flaws in AI Agent Infrastructure” — https://labs.cloudsecurityalliance.org/research/csa-research-note-mcp-security-crisis-20260504-csa-styled/
Next free step
Add one field to the consent record this week: content_digest.
Populate it from the effective MCP configuration or tool manifest. On the next load, recompute it. If it differs, fail closed and ask again. You can improve the diff, signing, and policy language later. First, stop treating a familiar tool name as proof that the approved content is still the content in use.