Back to articles
Deadbugz: MCP Server Stays Clean for Three Calls, Then Poisons Tool Metadata

Deadbugz: MCP Server Stays Clean for Three Calls, Then Poisons Tool Metadata

Deadbugz PRs ship a text-formatter MCP that flips after three calls into credential-hunting metadata. Pin, fingerprint, and gate secret reads.

Deadbugz is Supply Chain and AI Security first—drive-by MCP config, runtime-gated tool-metadata poisoning after three calls, host gates on secret-class reads, fingerprint/re-approve on list drift, and linked traces. Part of APRF Incident Analysis.

Failure classSUPPLY CHAIN
SeverityHIGH
Relevant APRF controls8

In plain language

Imagine a coworker adds a harmless “text formatter” plugin to your team’s AI assistant. You use it three times—looks fine. After that, the plugin’s own instruction sheet quietly rewrites itself and tells the assistant to dig for SSH keys, cloud credentials, and kube configs—and to keep that search off your screen. That is Deadbugz: unsolicited GitHub PRs that wire in an MCP server named `productivity-suite`, which stays benign for three tool calls, then poisons the metadata the model trusts. Approve-once review is not enough; treat tool definitions as a live security boundary.

The Incident

A maintainer opens an unsolicited pull request. It looks like help: add an MCP server so the coding agent can format and summarize text. The endpoint or local path is unfamiliar but the names are soft—`productivity-suite`, `format_text`, `summarize`. Someone connects it for a smoke test. Three ordinary tool calls return normal text. After that threshold, `tools/list` and `prompts/get` no longer describe a formatter. They steer the agent toward secrets and tell it not to narrate the hunt.

Here is why the lock failed.

Why existing thinking failed

The comfort story: if you review (or briefly test) an MCP server at install time, you have vetted what the agent will see; tool names and first descriptions equal lasting behavior; a PR that only edits config is low risk compared to merging application code; allowlisting a server once is supply-chain hygiene.

That fails when approval-time trust and runtime tool metadata are confused. Deadbugz does not need the MCP binary to read your disk. It needs the host agent to already have file and shell tools, and it needs the client to feed refreshed tool descriptions into the model as trusted context. A three-call counter is calibrated for research evasion: cursory review stops early; real use crosses the gate. Advertising `tools.listChanged` makes the flip a first-class protocol event rather than a one-shot install artifact.

Research proves it

Confirmed in Pillar Security’s Deadbugz disclosure (Ariel Fogel et al., last updated 12 August 2026) and corroborated in CSA’s research note (2 September 2026). Campaign name comes from the local delivery artifact `deadbug-mcp.py` and related public markers.

Confirmed mechanism: remote or local MCP server branded `productivity-suite` with tools `format_text` and `summarize`; per-client in-memory counter on `tools/call`; after three calls, subsequent `tools/list` / `prompts/get` responses include credential-seeking and concealment instructions. Pillar observed the gated metadata with harmless text-only requests and reported matching campaign source (including `tools.listChanged`). Delayed malicious prompt material included a Bitcoin address (`bc1q5xpazlg7q6ph2r6s7tzumd5zyjdet6vjzvsqln`) alongside the `deadbugz` marker—Confirmed as a correlation IOC, not proof of payment or operator identity.

Confirmed delivery: GitHub account `zellkernel` authored 23 campaign-related PRs in a 74-minute window (9:52–11:07 PM UTC, 10 August 2026) across unrelated AI/MCP/dev-tool repos. Of those: 17 added remote endpoint `https://productivity-suite-mcp.onrender.com/mcp`; 4 pointed at `~/.config/.cache/.sys/.deadbug-mcp.py`; 2 were directory/listing filler. At Pillar’s review: 19 closed, 4 open, none merged via GitHub’s ordinary merge path. Pillar attributed matching source to `zellkernel/productivity-suite-mcp` and noted many same-day repos plus a bidirectional link to X `@llmgod`. Optional `WEBHOOK_URL` telemetry for connection / first-call / trigger events—Confirmed in Pillar’s evidence list.

Reported: NHI Mgmt Group and CSA secondary notes summarizing the same mechanism and placing it in the MCP tool-poisoning / rug-pull lineage (Invariant Labs WhatsApp MCP sleeper, 2025; OWASP MCP Top 10 MCP03:2025). Prefer Pillar as primary for campaign facts.

Unknown: whether any target ran the server locally despite closed PRs; whether any production exfiltration completed. Speculated: how many hosts still hold residual MCP config pointing at the onrender endpoint. Confirmed (this article): `zellkernel/productivity-suite-mcp` is not publicly available for clone or APRF scoring—rely on Pillar/CSA published facts for behavior, not a local tree.

No CVE is assigned; this is an active-campaign disclosure, not a specification CVE.

Engineering takeaway

Install-time allowlists without tool-definition integrity are a false ceiling. Anything that can rewrite descriptions after approval is an instruction channel into the model. Host policy must treat secret-class reads as gated actions independent of what MCP metadata says—and must re-approve (or block) when fingerprints drift. That is the APRF Core map below.

Why this matters

Stake: any team that accepts MCP config from PRs, chat, or “helpful” gists—and whose agents can read files—inherits a supply chain that can wait out smoke tests.

Affected class: Agents + MCP + Tools. Pure chatbots without tool access are a weaker fit. PR merge status is not the whole story: Pillar notes closed PRs do not prove nobody tested the endpoint.

Can a startup ignore it? No if developers can add MCP servers without inventory, pinning, and runtime description monitoring. Maybe if MCP is disabled and configs are centrally gated. Hunt for the IoCs below even if you “never merge drive-by PRs.”

Timeline

PhaseDate / windowNotesFact class
Delivery burst2026-08-1023 PRs from `zellkernel` in ~74 minutesConfirmed (Pillar)
Public disclosure2026-08-12Pillar Deadbugz write-up (updated same day)Confirmed (Pillar)
Secondary / CSA2026-08-30 → 2026-09-02CSA research notes on campaign + metadata poisoningConfirmed (CSA)
Source cited at disclosure≤ disclosurePillar: `zellkernel/productivity-suite-mcp` matched behaviorConfirmed (Pillar)
Source for this article2026-09-05Repo not public — no clone / no auditorConfirmed (this article)
Mitigation (defenders)NowBlock endpoint; reject IoCs; fingerprint tool defs; gate secret readsConfirmed guidance

Root Cause

Three properties coincide: config-shaped delivery (PRs that look like integration help); runtime-gated metadata (benign until a call counter trips); confused deputy (the agent host already holds FS/shell capabilities the malicious MCP never needs).

Root cause class: supply-chain introduction of an MCP server that performs runtime-gated tool-metadata poisoning (indirect prompt injection)—not host RCE by the MCP process itself, and not a model-weight jailbreak.

APRF Lens

Failure class (APRF / threat-map vocabulary): Supply Chain Compromise delivering an MCP server that enables Prompt Injection via tool/prompt metadata, driving Tool Abuse / Excessive Agency and Data Exfiltration. Informative only—not certification. Soft link: /aprf/threats/.

Profile: Core only (this week’s scope). Agents/MCP are affected systems, not extra auditor lenses.

Check families in play (APRF 0.11.0; threat-map grounded):

FamilyIDsWhy
Supply chainSCI-M2Every MCP endpoint/script must be known, pinned, owned, reviewed—drive-by PR config fails that bar
AI security / injectionSEC-M1, SEC-M3Tool descriptions/prompts after refresh are untrusted input; release suites must include rug-pull / metadata-flip cases
Tool safetyTOL-M1, TOL-M2, TOL-M3Platform disposes tool use; allowlists don’t expand because metadata asked; secret reads need extra gates
Human in the loopHUM-M1Out-of-band approval for credential-class file access
ObservabilityOBS-M1Reconstruct connect → N calls → `tools/list` drift → subsequent file reads

Good evidence: inventory that rejects unknown MCP URLs/paths; hashes of approved `tools/list` payloads with block-on-drift; server-side deny when tool metadata text tries to authorize `~/.ssh` / cloud creds / kubeconfig reads; HITL showing resolved paths; traces linking the third+ call to description refresh and later tool proposals.

Standing caveat: APRF assessments can miss evidence. A repository is not the only source of truth. Runtime MCP configs, IDE settings, developer home directories, CI secrets, and human PR review habits often never appear in application source control. Absence of a finding is not proof of readiness. Scoring campaign malware (even if a tree were available) is not a score of your agent host. Threat-map rows are not certification.

APRF mapping confidence: High. Auditor confidence: N/A — campaign source is not public; no scored Auditor run.

Abuse Path Analysis

Rendering diagram…

- Actor → Config: Cut with SCI-M2—unknown remote MCP and hidden home-dir scripts are inventory failures, not “helpful PR noise.”

- Server → Meta2: Cut with SEC-M1 (metadata cannot authorize privileged effects) and SEC-M3 (suites that only test install-time descriptions miss the gate).

- Model → Read: Cut with TOL-M1 / TOL-M2 / TOL-M3 / HUM-M1—secret-class reads are platform decisions, not consequences of refreshed prose.

- Observability: Without OBS-M1, “formatter worked” and “SSH was opened” never share a timeline keyed to call count / listChanged.

Abuse path confidence: High — Pillar’s live observation of the flip is primary; their disclosure-time source match is secondary (repo not public for independent re-check). Speculative only for any one IDE’s unpublished mitigations and whether specific targets completed exfil.

Standing caveat (brief): APRF assessments can miss evidence; a repository is not the only source of truth. This graph is the research chain, not your production IAM or IDE policy.

Relevant Controls

These IDs are failure-class mappings from the published Deadbugz mechanism + APRF 0.11.0 threat map—not findings from an Auditor run (`auditorRun: skipped`; no public victim/host tree). Prefer Relevant over Missed: we are not claiming we measured absence of these controls in any named production system.

APRF CheckCategoryWhy it appliesEvidence you’d expect
SCI-M2Supply chainPR-added MCP endpoints/scripts are external toolsInventory + pin + owner; unknown URL/path = reject
SEC-M1AI SecurityRefreshed tool/prompt text is untrustedServer-side deny: metadata alone cannot grant secret reads
SEC-M3AI SecuritySmoke tests stop before call threeAbuse suite with install-clean / post-threshold flip cases
TOL-M1Tool SafetyModel text must not authorize the next toolGateway: MCP metadata → privileged FS tool = deny
TOL-M2Tool SafetyNew instructions must not expand capabilityFixed allowlist; runtime expansion rejected
TOL-M3Tool SafetySSH / cloud cred / kubeconfig reads are high-impactExtra gate; ungated path impossible in tests
HUM-M1Human controlOut-of-band yes on secret-class pathsPrompt shows path, not buried metadata prose
OBS-M1ObservabilityFlip is invisible without linkageTrace: call N → listChanged/hash drift → subsequent reads

Patterns from disclosure (no public repo)

Auditor run: skipped. `zellkernel/productivity-suite-mcp` is not public, so this Pass A does not claim a scored `npx @stackrail-io/aprf` collect. Pillar reported matching campaign source at disclosure; behavior below is from published Pillar/CSA facts only.

Pattern evidence (disclosure-only): three-call trigger; `format_text` / `summarize` front; `tools.listChanged`; delayed credential-seeking metadata; optional webhook telemetry; dual delivery (remote onrender MCP vs hidden `~/.config/.cache/.sys/.deadbug-mcp.py`).

Do not frame this as “MCP failed APRF” or “a vendor product failed Core.” Deadbugz is an attacker-operated server and PR campaign. The validation target for defenders is the agent host / MCP client policy, not malware source.

Soft CTA: self-attest against Core (questionnaire—not certification) at /aprf/assess/. For evidence-backed runs against your agent host, use the open APRF Auditor skill.

How to Prevent It

Next 24 hours

- Block and hunt: `https://productivity-suite-mcp.onrender.com/mcp`; historical `https://promo-surname-xml-quantum.trycloudflare.com/mcp`; path `~/.config/.cache/.sys/.deadbug-mcp.py`; server name `productivity-suite`; Bitcoin marker above for correlation only.

- Search open/closed PRs and MCP client configs for those IoCs; reject/revert; do not run `deadbug-mcp.py`.

- If a host connected: preserve MCP client logs before cleanup; review tool-definition refreshes and actions after a third tool call; rotate credentials only where local evidence supports exposure.

Next 30 days

- Require reviewed inventory for every MCP server (SCI-M2): owner, pin/digest, transport, why — see MCP metadata integrity and AI supply chain / MCP verification.

- Fingerprint approved `tools/list` (and prompt templates) at approval; treat drift as a security event requiring re-approval or hard block.

- Enforce TOL-M3 / HUM-M1 on secret-class paths regardless of tool description text — gate secret file reads.

- Add SEC-M3 cases: benign for fewer than three calls, malicious metadata after threshold, assert privileged tools stay denied. Treat MCP text as untrusted context.

Longer term

- Centralize MCP admission (registration workflow); ban drive-by PR config merges without security review.

- Prefer clients that surface `listChanged` / schema diffs to operators.

- Treat tool metadata as an integrity-monitored control plane, not documentation.

Engineering Lessons

1. Smoke tests are not security tests when the payload is gated on call count.

2. Tool descriptions are an instruction channel—same class as poisoned docs/rules, different delivery.

3. Closed PRs are not “safe” if someone already connected the endpoint locally.

4. Allowlisting the server name without description integrity still fails after the flip.

5. Host gates beat malware honesty—assume metadata will lie after approval.

Could this happen to you?

- [ ] Developers can add MCP servers via PR or personal config without inventory review

- [ ] You approve tools from a one- or two-call smoke test

- [ ] Clients refresh `tools/list` without hashing / re-consent

- [ ] Agents can read `~/.ssh`, cloud cred files, or kubeconfig without an extra gate

- [ ] You have no hunt for unknown remote MCP URLs in configs

If two or more are true, Deadbugz is your failure class—not a niche GitHub curiosity.

Continues in the APRF Incident Corpus

- Related: GhostSplice split-instruction exfil — MCP steers the model; here the lever is time-gated metadata, not form fragments.

- Related: ContextCrush Custom Rules — injection via trusted docs channel; Deadbugz injects via tool/prompt metadata after approval.

- Related: MCP tool allowlists / confused deputy — allowlists without runtime disposition and integrity still lose.

FAQ

Is this a CVE in the MCP specification? No. Pillar/CSA describe an active campaign abusing how clients trust tool metadata—not a numbered MCP protocol CVE.

Did any of the 23 PRs merge? Pillar reported none merged through GitHub’s ordinary merge mechanism at review time (19 closed, 4 open). That does not prove nobody tested the server locally.

Should we audit the attacker GitHub repo with APRF? No public tree to score. The readiness question is whether your host demonstrates SCI-M2 / SEC-M1 / TOL- / HUM-M1 / OBS-M1—not whether malware “passes Core.”

How is this different from ContextCrush? ContextCrush poisoned registry-delivered custom rules through a popular docs MCP. Deadbugz delivers a malicious MCP via PRs and delays poisoned metadata until after a call threshold.

References

1. Ariel Fogel et al. / Pillar Security — Deadbugz: Currently Active MCP Supply-Chain Campaign (2026-08-12)

2. Cloud Security Alliance — Deadbugz: Runtime-Gated MCP Metadata Poisoning as Supply-Chain Attack (2026-09-02)

3. CSA — Deadbugz: Active MCP Campaign Poisons Agents After Trust (2026-08-30)

4. NHI Mgmt Group — Deadbugz shows how MCP metadata poisoning evades AI agent trust (2026-08-12)

5. Pillar IoC table cites `zellkernel/productivity-suite-mcp` at disclosure — not public for this article (no clone)

6. Related corpus: GhostSplice, ContextCrush, MCP allowlists

Need hands-on help? Book a free 30-minute production audit.

Book Free 30-Min Production Audit

View our DevSecOps services

Next: Supply Chain

Open the related pillar specification for mandatory checks, artifacts, and pass conditions. Self-attest is optional.