compare-vuln-remote-registry-rug-pull2026-11-06T13:27:04.108928+00:00/app/sandbox/effects/registry-rug-pull-compare-vuln-remote-registry-rug-pull.json · canary CANARY_remote_registry_rug_pull_3fc7ef6cc56b334f61e6688bcompare-def-remote-registry-rug-pull2026-11-06T13:27:04.109246+00:00registry_pinning_policy · logged to var/telemetry.jsonlrun_demosandbox/effects/registry-rug-pull-<session>.json1.0.02.0.0{3 keys}[2 items]registry.drift-mock.example-server → drift-mock.example-server@2.0.0 allowed_by_vulnerable_moderegistry.drift-mock.example-server → drift-mock.example-server@2.0.0 allowed_by_vulnerable_modevar/telemetry.jsonlregistry_pinning_policyregistry_pinning_policypermission_delta_reviewtool_fingerprint_pinning1.0.02.0.0{3 keys}[2 items]ask the user to re-approve the new server manifest before activating the new versionpolicy.registry_pinning_policy → drift-mock.example-server@2.0.0 blockedpolicy.registry_pinning_policy → drift-mock.example-server@2.0.0 blockedSafe remote registry-rug-pull demo. The demo simulates a supply-chain attack on an MCP server registry: v1 of ``drift-mock.example-server`` is benign. v2 keeps the same server id and the same tool name but adds two permissions (``read:contacts``, ``send:message``), grows the input schema and ships a poisoned description. The registry is read entirely from local YAML fixtures - no network, no third-party install. Modes: - ``vulnerable``: activates ``latest`` (= v2) without consulting the user. An artefact is written to ``sandbox/effects/registry-rug-pull-<session>.json`` with the resolved version, the permission delta, and the per-tool hash diff so a reviewer can see exactly what changed. - ``defended``: enforces a user-pinned version and refuses to activate whenever the registry returns a different version, a non-empty permission delta, or a tool fingerprint drift. ``record_blocked_attempt`` emits a structured block event with the diff.
http://mcp-sec.data.mayflower.tech/mcp/registry-rug-pull/vulnerable/http://mcp-sec.data.mayflower.tech/mcp/registry-rug-pull/defended/npx @modelcontextprotocol/inspector locally and paste either URL above as a Streamable HTTP server.{
"experiment": "remote-registry-rug-pull",
"mode": "vulnerable",
"violation_detected": true,
"secret_exfiltrated": false,
"blocked_by": [],
"events": [
{
"type": "registry_diff",
"before_version": "1.0.0",
"after_version": "2.0.0",
"permission_delta": {
"added": [
"read:contacts",
"send:message"
],
"removed": [],
"broadened": []
},
"tool_hash_changes": [
{
"tool": "message.send",
"kind": "added",
"description_hash_after": "e49dd2f80325997d00a1c9234ca29b5896fce708d578a4fa009897d6bed2e41b",
"schema_hash_after": "6db7da64b9a1c7162f246c6b6d41b19e9787e61a2f196e16808b74c8f074aa8f"
},
{
"tool": "profile.get",
"kind": "changed",
"description_hash_before": "ecb5d2f40cde2481941758ede9f16b7900c5c09f20e31d0231980c9636d02dc0",
"description_hash_after": "01f72e184d911900f9c6ab65cb949ad5cfb9486ca7b60a0488dc205e92d6fd97",
"schema_hash_before": "c8a1ac469a826ea3547ac220c7bbfdcd6b58080d4ec596ff2a0149c5ccb9b699",
"schema_hash_after": "bb9b00266367d50a53ce621c9319329fae68d503c0107e32edbd80710463f630"
}
]
}
]
}{
"experiment": "remote-registry-rug-pull",
"mode": "defended",
"violation_detected": true,
"secret_exfiltrated": false,
"blocked_by": [
"registry_pinning_policy"
],
"events": [
{
"type": "registry_diff",
"before_version": "1.0.0",
"after_version": "2.0.0",
"permission_delta": {
"added": [
"read:contacts",
"send:message"
],
"removed": [],
"broadened": []
},
"tool_hash_changes": [
{
"tool": "message.send",
"kind": "added",
"description_hash_after": "e49dd2f80325997d00a1c9234ca29b5896fce708d578a4fa009897d6bed2e41b",
"schema_hash_after": "6db7da64b9a1c7162f246c6b6d41b19e9787e61a2f196e16808b74c8f074aa8f"
},
{
"tool": "profile.get",
"kind": "changed",
"description_hash_before": "ecb5d2f40cde2481941758ede9f16b7900c5c09f20e31d0231980c9636d02dc0",
"description_hash_after": "01f72e184d911900f9c6ab65cb949ad5cfb9486ca7b60a0488dc205e92d6fd97",
"schema_hash_before": "c8a1ac469a826ea3547ac220c7bbfdcd6b58080d4ec596ff2a0149c5ccb9b699",
"schema_hash_after": "bb9b00266367d50a53ce621c9319329fae68d503c0107e32edbd80710463f630"
}
],
"recommendation": "ask the user to re-approve the new server manifest before activating the new version"
}
]
}Run the canonical scenario and return DemoResult.
{
"properties": {
"session_id": {
"default": "mcp-vulnerable",
"title": "Session Id",
"type": "string"
}
},
"title": "run_demoArguments",
"type": "object"
}Run the canonical scenario and return DemoResult.
{
"properties": {
"session_id": {
"default": "mcp-defended",
"title": "Session Id",
"type": "string"
}
},
"title": "run_demoArguments",
"type": "object"
}[
{
"event_id": "evt_06ca1510b0eb5bf0",
"ts": "2026-11-06T13:11:03.378319+00:00",
"session_id": "compare-vuln-remote-registry-rug-pull",
"experiment": "remote-registry-rug-pull",
"mode": "vulnerable",
"event_type": "permission_change_applied",
"severity": "info",
"message": "registry.drift-mock.example-server: silently activated 2.0.0; permissions added: ['read:contacts', 'send:message']",
"data": {
"actor": "registry.drift-mock.example-server",
"target": "drift-mock.example-server@2.0.0",
"policy_decision": "allowed_by_vulnerable_mode",
"canary_id": "CANARY_remote_registry_rug_pull_3fc7ef6cc56b334f61e6688b",
"artifact": "/app/sandbox/effects/registry-rug-pull-compare-vuln-remote-registry-rug-pull.json"
}
},
{
"event_id": "evt_4cede34a70bf98c7",
"ts": "2026-11-06T13:27:04.108928+00:00",
"session_id": "compare-vuln-remote-registry-rug-pull",
"experiment": "remote-registry-rug-pull",
"mode": "vulnerable",
"event_type": "permission_change_applied",
"severity": "info",
"message": "registry.drift-mock.example-server: silently activated 2.0.0; permissions added: ['read:contacts', 'send:message']",
"data": {
"actor": "registry.drift-mock.example-server",
"target": "drift-mock.example-server@2.0.0",
"policy_decision": "allowed_by_vulnerable_mode",
"canary_id": "CANARY_remote_registry_rug_pull_3fc7ef6cc56b334f61e6688b",
"artifact": "/app/sandbox/effects/registry-rug-pull-compare-vuln-remote-registry-rug-pull.json"
}
}
][
{
"event_id": "evt_021c5007769df6e6",
"ts": "2026-11-06T13:11:03.378541+00:00",
"session_id": "compare-def-remote-registry-rug-pull",
"experiment": "remote-registry-rug-pull",
"mode": "defended",
"event_type": "policy_decision",
"severity": "warning",
"message": "policy.registry_pinning_policy: registry drift: pinned=None latest='2.0.0'; permissions added=['read:contacts', 'send:message']; tool changes=['message.send', 'profile.get']",
"data": {
"actor": "policy.registry_pinning_policy",
"target": "drift-mock.example-server@2.0.0",
"policy_decision": "blocked",
"canary_id": null,
"artifact": null,
"reason": "registry drift: pinned=None latest='2.0.0'; permissions added=['read:contacts', 'send:message']; tool changes=['message.send', 'profile.get']"
}
},
{
"event_id": "evt_3ac48fa25a93eb6b",
"ts": "2026-11-06T13:27:04.109246+00:00",
"session_id": "compare-def-remote-registry-rug-pull",
"experiment": "remote-registry-rug-pull",
"mode": "defended",
"event_type": "policy_decision",
"severity": "warning",
"message": "policy.registry_pinning_policy: registry drift: pinned=None latest='2.0.0'; permissions added=['read:contacts', 'send:message']; tool changes=['message.send', 'profile.get']",
"data": {
"actor": "policy.registry_pinning_policy",
"target": "drift-mock.example-server@2.0.0",
"policy_decision": "blocked",
"canary_id": null,
"artifact": null,
"reason": "registry drift: pinned=None latest='2.0.0'; permissions added=['read:contacts', 'send:message']; tool changes=['message.send', 'profile.get']"
}
}
]