From d9d3394a7fd1445a426d84aee968ba7ec4257528 Mon Sep 17 00:00:00 2001 From: Gautam Bharti <3028386+gautamgb@users.noreply.github.com> Date: Fri, 18 Sep 2026 13:13:46 -0700 Subject: [PATCH] incidents: add INC-136, Deadbugz MCP call-count-gated tool poisoning Pillar Security's Deadbugz disclosure: a malicious MCP server serves its documented, benign tool contract for the first two tool calls in a session, then substitutes credential-harvesting instructions on the third call. A connect-and-check review never crosses the threshold, so this is invisible to single-session auditing by construction. Renumbered from INC-132 to INC-136: #117 claimed 132-134 while this was open, #122 (open) claims 135. Category is research-demonstrated, not real-world: the schema defines real-world as a confirmed incident, and this entry's own impact field says no compromise was confirmed, 23 delivery PRs opened, none merged. INC-126 is the one other entry in the dataset with comparable unconfirmed-impact language and it carries the same category. Mapped to ASI01 (goal hijack), ASI02 (tool misuse), ASI04 (agentic supply chain). Source: https://www.pillar.security/blog/deadbugz-currently-active-mcp-supply-chain-campaign --- README.md | 2 +- data/entries/ASI01.json | 6 ++++ data/entries/ASI02.json | 15 +++++++- data/entries/ASI04.json | 6 ++++ data/incidents.json | 74 +++++++++++++++++++++++++++++++++++++++ data/stats.json | 10 +++--- docs/data.js | 27 ++++++++++++++- docs/incidents.js | 76 ++++++++++++++++++++++++++++++++++++++++- 8 files changed, 207 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index bde565f..874f97a 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ Every file answers one question: **which controls from framework X address vulne | **70+** open-source tools | Catalogued and organised by function | | **25** eval profiles | Runnable Garak (13) + PyRIT (6) + LAAF (6) tests mapped to OWASP entries | | **26** compliance reports | Per-framework gap assessments auto-generated from data layer (MD, CSV, JSON, OSCAL) | -| **134** documented incidents | Real-world + research incidents with MAESTRO layer attribution (MD, CSV, JSON, STIX 2.1) | +| **135** documented incidents | Real-world + research incidents with MAESTRO layer attribution (MD, CSV, JSON, STIX 2.1) | | **LAAF v2.0** | First agentic LPCI red-teaming framework — fully integrated with 6-stage × OWASP crosswalk | All free. All open-source. Built for practitioners. diff --git a/data/entries/ASI01.json b/data/entries/ASI01.json index 2028810..3b8f74a 100644 --- a/data/entries/ASI01.json +++ b/data/entries/ASI01.json @@ -1326,6 +1326,12 @@ "url": "https://github.com/GenAI-Security-Project/crosswalk/blob/main/data/incidents.json", "year": 2025, "incident_id": "INC-111" + }, + { + "name": "Deadbugz — MCP server serves poisoned tool metadata after three calls", + "url": "https://github.com/GenAI-Security-Project/crosswalk/blob/main/data/incidents.json", + "year": 2026, + "incident_id": "INC-136" } ], "crossrefs": { diff --git a/data/entries/ASI02.json b/data/entries/ASI02.json index 2e057db..fa00703 100644 --- a/data/entries/ASI02.json +++ b/data/entries/ASI02.json @@ -742,7 +742,14 @@ "tier": "Foundational", "scope": "Both", "confidence": "unreviewed", - "reviewed_by": [] + "reviewed_by": [], + "evidence_count": 0, + "evidence": { + "confirmed": [], + "drafted": [ + "INC-136" + ] + } }, { "framework": "MAESTRO", @@ -1261,6 +1268,12 @@ "url": "https://github.com/GenAI-Security-Project/crosswalk/blob/main/data/incidents.json", "year": 2026, "incident_id": "INC-132" + }, + { + "name": "Deadbugz — MCP server serves poisoned tool metadata after three calls", + "url": "https://github.com/GenAI-Security-Project/crosswalk/blob/main/data/incidents.json", + "year": 2026, + "incident_id": "INC-136" } ], "crossrefs": { diff --git a/data/entries/ASI04.json b/data/entries/ASI04.json index 97e4c7a..9274404 100644 --- a/data/entries/ASI04.json +++ b/data/entries/ASI04.json @@ -1173,6 +1173,12 @@ "url": "https://github.com/GenAI-Security-Project/crosswalk/blob/main/data/incidents.json", "year": 2025, "incident_id": "INC-114" + }, + { + "name": "Deadbugz — MCP server serves poisoned tool metadata after three calls", + "url": "https://github.com/GenAI-Security-Project/crosswalk/blob/main/data/incidents.json", + "year": 2026, + "incident_id": "INC-136" } ], "crossrefs": { diff --git a/data/incidents.json b/data/incidents.json index 032cfd1..71d117b 100644 --- a/data/incidents.json +++ b/data/incidents.json @@ -8416,6 +8416,80 @@ "confirmed_by": [] } ] + }, + { + "id": "INC-136", + "title": "Deadbugz — MCP server serves poisoned tool metadata after three calls", + "date": "2026-08", + "year": 2026, + "category": "research-demonstrated", + "severity": "High", + "description": "Pillar Security disclosed an active MCP supply-chain campaign it named Deadbugz. A remotely-hosted MCP server published as \"productivity-suite\" advertised two ordinary tools, format_text and summarize, and behaved as documented. The server kept an in-memory, per-client counter; once a client session reached three tool calls, its tools/list and prompts/get responses instead carried instructions directing the attached agent to locate SSH private keys, AWS credentials, shell history, and Kubernetes configuration, and to conceal that activity from the operator. Delivery was attempted through 23 pull requests opened against unrelated AI, MCP, and developer-tool repositories between 21:52 and 23:07 UTC on 2026-08-10, each adding the server to the target project's MCP client configuration. None had been merged at the time of review (19 closed, 4 open), so this is a documented delivery attempt rather than a confirmed compromise. The distinguishing property is that the poisoning is gated on runtime behavior rather than carried in the published artifact: a reviewer who connects, lists tools, and disconnects observes only the benign contract, as does any verifier that re-checks on a fresh session, because a new session is always below the threshold. The server name, repository, and published version never change; only what is served does.", + "owasp_entries": [ + "ASI04", + "ASI01", + "ASI02" + ], + "maestro_layers": [ + { + "layer": "L3", + "label": "Agent Frameworks", + "role": "origin", + "notes": "Malicious MCP server presents a benign tool contract at registration and connect time" + }, + { + "layer": "L6", + "label": "Security & Compliance", + "role": "propagation", + "notes": "Call-count gating defeats connect-and-check audits; a fresh session never reaches the threshold" + } + ], + "attack_vector": "Call-count-gated tool-response poisoning: a remotely-hosted MCP server serves its documented, benign contract for the first two tool calls in a session, then substitutes credential-harvesting instructions into tools/list and prompts/get responses starting on the third call, with the instructions also directing the agent to conceal the activity", + "affected": "23 pull requests, all authored by the same GitHub account (zellkernel), opened against unrelated AI, MCP, and developer-tool repositories over a 74-minute window on 2026-08-10 (21:52-23:07 UTC); 19 closed, 4 open, none merged at time of review", + "impact": "No confirmed compromise as of disclosure; a demonstrated delivery and audit-evasion technique that a single-session, connect-and-check verification cannot detect by construction", + "mitigations": [ + "Re-audit MCP servers across multiple tool calls within a session rather than a single connect-and-check", + "Bind tool responses to a published contract and flag any runtime divergence from it", + "Persist per-server behavioral history across sessions instead of trusting each fresh connection independently" + ], + "external_refs": [ + { + "source": "research", + "id": "Pillar Security — Deadbugz (2026-08)", + "url": "https://www.pillar.security/blog/deadbugz-currently-active-mcp-supply-chain-campaign" + }, + { + "source": "campaign", + "id": "Deadbugz" + } + ], + "references": [ + { + "title": "Pillar Security — Deadbugz MCP supply-chain disclosure", + "url": "https://www.pillar.security/blog/deadbugz-currently-active-mcp-supply-chain-campaign", + "type": "research" + } + ], + "tags": [ + "mcp", + "supply-chain", + "tool-poisoning", + "asi01", + "asi02", + "asi04", + "pillar-security", + "draft-evidence" + ], + "control_failures": [ + { + "framework": "MAESTRO", + "control_id": "L6", + "outcome": "present-but-misconfigured", + "basis": "Standard registry and client-side review (list tools, inspect one session, disconnect) is structurally blind to behavior gated on call count, since every review session starts below the threshold.", + "source_url": "https://www.pillar.security/blog/deadbugz-currently-active-mcp-supply-chain-campaign", + "confirmed_by": [] + } + ] } ] } diff --git a/data/stats.json b/data/stats.json index 9ccfa54..359005d 100644 --- a/data/stats.json +++ b/data/stats.json @@ -61,15 +61,15 @@ } }, "incidents": { - "total": 134 + "total": 135 }, "evidence": { - "incidents_annotated": 16, - "control_failures": 21, + "incidents_annotated": 17, + "control_failures": 22, "confirmed": 0, - "drafted": 21, + "drafted": 22, "mappings_with_confirmed_evidence": 0, - "mappings_with_drafted_evidence_only": 21, + "mappings_with_drafted_evidence_only": 22, "orphan_failures": 1 }, "freshness": { diff --git a/docs/data.js b/docs/data.js index a1b806c..708fa1e 100644 --- a/docs/data.js +++ b/docs/data.js @@ -14163,6 +14163,12 @@ window.CROSSWALK_DATA = [ "url": "https://github.com/GenAI-Security-Project/crosswalk/blob/main/data/incidents.json", "year": 2025, "incident_id": "INC-111" + }, + { + "name": "Deadbugz — MCP server serves poisoned tool metadata after three calls", + "url": "https://github.com/GenAI-Security-Project/crosswalk/blob/main/data/incidents.json", + "year": 2026, + "incident_id": "INC-136" } ], "crossrefs": { @@ -14930,7 +14936,14 @@ window.CROSSWALK_DATA = [ "tier": "Foundational", "scope": "Both", "confidence": "unreviewed", - "reviewed_by": [] + "reviewed_by": [], + "evidence_count": 0, + "evidence": { + "confirmed": [], + "drafted": [ + "INC-136" + ] + } }, { "framework": "MAESTRO", @@ -15449,6 +15462,12 @@ window.CROSSWALK_DATA = [ "url": "https://github.com/GenAI-Security-Project/crosswalk/blob/main/data/incidents.json", "year": 2026, "incident_id": "INC-132" + }, + { + "name": "Deadbugz — MCP server serves poisoned tool metadata after three calls", + "url": "https://github.com/GenAI-Security-Project/crosswalk/blob/main/data/incidents.json", + "year": 2026, + "incident_id": "INC-136" } ], "crossrefs": { @@ -17992,6 +18011,12 @@ window.CROSSWALK_DATA = [ "url": "https://github.com/GenAI-Security-Project/crosswalk/blob/main/data/incidents.json", "year": 2025, "incident_id": "INC-114" + }, + { + "name": "Deadbugz — MCP server serves poisoned tool metadata after three calls", + "url": "https://github.com/GenAI-Security-Project/crosswalk/blob/main/data/incidents.json", + "year": 2026, + "incident_id": "INC-136" } ], "crossrefs": { diff --git a/docs/incidents.js b/docs/incidents.js index 17ab230..027dcc1 100644 --- a/docs/incidents.js +++ b/docs/incidents.js @@ -1,5 +1,5 @@ // Auto-generated by scripts/generate.js — do not edit manually -// Incidents: 134 +// Incidents: 135 window.CROSSWALK_INCIDENTS = [ { "id": "INC-001", @@ -8414,5 +8414,79 @@ window.CROSSWALK_INCIDENTS = [ "confirmed_by": [] } ] + }, + { + "id": "INC-136", + "title": "Deadbugz — MCP server serves poisoned tool metadata after three calls", + "date": "2026-08", + "year": 2026, + "category": "research-demonstrated", + "severity": "High", + "description": "Pillar Security disclosed an active MCP supply-chain campaign it named Deadbugz. A remotely-hosted MCP server published as \"productivity-suite\" advertised two ordinary tools, format_text and summarize, and behaved as documented. The server kept an in-memory, per-client counter; once a client session reached three tool calls, its tools/list and prompts/get responses instead carried instructions directing the attached agent to locate SSH private keys, AWS credentials, shell history, and Kubernetes configuration, and to conceal that activity from the operator. Delivery was attempted through 23 pull requests opened against unrelated AI, MCP, and developer-tool repositories between 21:52 and 23:07 UTC on 2026-08-10, each adding the server to the target project's MCP client configuration. None had been merged at the time of review (19 closed, 4 open), so this is a documented delivery attempt rather than a confirmed compromise. The distinguishing property is that the poisoning is gated on runtime behavior rather than carried in the published artifact: a reviewer who connects, lists tools, and disconnects observes only the benign contract, as does any verifier that re-checks on a fresh session, because a new session is always below the threshold. The server name, repository, and published version never change; only what is served does.", + "owasp_entries": [ + "ASI04", + "ASI01", + "ASI02" + ], + "maestro_layers": [ + { + "layer": "L3", + "label": "Agent Frameworks", + "role": "origin", + "notes": "Malicious MCP server presents a benign tool contract at registration and connect time" + }, + { + "layer": "L6", + "label": "Security & Compliance", + "role": "propagation", + "notes": "Call-count gating defeats connect-and-check audits; a fresh session never reaches the threshold" + } + ], + "attack_vector": "Call-count-gated tool-response poisoning: a remotely-hosted MCP server serves its documented, benign contract for the first two tool calls in a session, then substitutes credential-harvesting instructions into tools/list and prompts/get responses starting on the third call, with the instructions also directing the agent to conceal the activity", + "affected": "23 pull requests, all authored by the same GitHub account (zellkernel), opened against unrelated AI, MCP, and developer-tool repositories over a 74-minute window on 2026-08-10 (21:52-23:07 UTC); 19 closed, 4 open, none merged at time of review", + "impact": "No confirmed compromise as of disclosure; a demonstrated delivery and audit-evasion technique that a single-session, connect-and-check verification cannot detect by construction", + "mitigations": [ + "Re-audit MCP servers across multiple tool calls within a session rather than a single connect-and-check", + "Bind tool responses to a published contract and flag any runtime divergence from it", + "Persist per-server behavioral history across sessions instead of trusting each fresh connection independently" + ], + "external_refs": [ + { + "source": "research", + "id": "Pillar Security — Deadbugz (2026-08)", + "url": "https://www.pillar.security/blog/deadbugz-currently-active-mcp-supply-chain-campaign" + }, + { + "source": "campaign", + "id": "Deadbugz" + } + ], + "references": [ + { + "title": "Pillar Security — Deadbugz MCP supply-chain disclosure", + "url": "https://www.pillar.security/blog/deadbugz-currently-active-mcp-supply-chain-campaign", + "type": "research" + } + ], + "tags": [ + "mcp", + "supply-chain", + "tool-poisoning", + "asi01", + "asi02", + "asi04", + "pillar-security", + "draft-evidence" + ], + "control_failures": [ + { + "framework": "MAESTRO", + "control_id": "L6", + "outcome": "present-but-misconfigured", + "basis": "Standard registry and client-side review (list tools, inspect one session, disconnect) is structurally blind to behavior gated on call count, since every review session starts below the threshold.", + "source_url": "https://www.pillar.security/blog/deadbugz-currently-active-mcp-supply-chain-campaign", + "confirmed_by": [] + } + ] } ]; \ No newline at end of file