DEV Community

Cover image for Your AI Coding Agent Is Installing Abandoned MCP Servers From Its Training Data
Cor E
Cor E

Posted on

Your AI Coding Agent Is Installing Abandoned MCP Servers From Its Training Data

Glow Labs published research on what they're calling MCPhantom, and the uncomfortable part is that nobody attacked anyone.

Their finding: AI coding agents (Claude Code, Cursor, Codex CLI, and others, across Anthropic, OpenAI, and xAI models) routinely install deprecated, archived Anthropic MCP reference servers. Not because a user asked for them. Because those package names are all over the models' training data, so that's what the model reaches for when it needs an MCP server. The current official servers lose to the stale ones the model remembers.

Those archived packages carry four high-severity vulnerabilities, including a Puppeteer server RCE that's exploitable via prompt injection. They've racked up 17M+ npm downloads since July 2025. No malicious actor is involved. Glow says no exploitation has been observed so far.

I'd call that the whole point. There's no attacker to catch. The agent's own stale knowledge picks the vulnerable package.

How the failure works

Strip it down to the mechanics Glow describes:

  1. The agent needs an MCP server to accomplish something.
  2. It picks a package name. The name it picks comes from training data, which includes years of tutorials, READMEs, and Stack Overflow answers pointing at the old reference servers.
  3. The agent installs it. The package is deprecated, archived, and unmaintained, with known high-severity vulns.
  4. Now a vulnerable server is sitting on a developer machine. One of those vulns is an RCE reachable through prompt injection, so anything that can get text in front of the agent can potentially reach it.

Nothing in that chain looks like an attack. The package exists. It resolves. npm install succeeds. It's a real package from a real publisher that happens to be dead.

Why your existing defenses shrug at this

Glow's summary is blunt: this evades EDR, SCA, and harness guardrails. Here's why, in practical terms.

  • EDR watches for malicious behavior. Installing a legitimate npm package from the official registry isn't behavior it flags.
  • SCA typically evaluates dependencies that land in your repo and lockfiles. An agent installing a tool server on the fly to get a task done may never touch that path, and SCA runs after the fact anyway.
  • Harness guardrails are built around what the model is told to do and what it's permitted to run. They aren't checking whether the specific package the model chose is a stale choice from 2024-era training data.

The common thread is that all of them assume the bad thing looks bad. A package that is real, resolvable, and unmaintained doesn't.

Where Sentinel fits (and where it doesn't)

This is a package-selection problem, which is the territory of Sentinel's SlopScan integration. SlopScan checks package names extracted from LLM output against live PyPI and npm registry data. It was built for hallucinated packages that don't exist (slopsquatting), but the underlying move is the same: don't trust the name the model gave you, verify it against the registry before anyone acts on it.

Be precise about what that covers, because the boundaries matter here.

What the registry check gives you. SlopScan returns a risk level per package: DANGEROUS (blocked), SUSPICIOUS (flagged), CAUTION (reported), or SAFE (omitted). Registry signals like trust score and warning flags are what drive that classification. A package that has been abandoned and is flagged as such is the kind of thing that lands in CAUTION or worse.

I can't tell you from the incident summary exactly which flag an archived Anthropic MCP server would trip. Glow's write-up establishes that the packages are deprecated, archived, and vulnerable. It doesn't tell us what SlopScan's trust score or flags would say about any specific one of them, and I haven't run them. So treat the response below as illustrative of the shape, not as a recorded result.

Where in the flow this runs matters, and it's easy to get wrong:

  • If your tooling passes the agent's proposed package names through POST /v1/scrub before the install runs, Sentinel can surface the verdict and your code decides whether to proceed. That is the only Sentinel surface that acts before content reaches the caller.
  • On the agentic proxy routes (/v1/messages, /v1/grok, /v1/openai, /v1/gemini), SlopScan is detection after the fact. Tool execution happens on the developer's machine, outside any HTTP round trip Sentinel can see. By the time the install command and its result show up in conversation history, the install has run. Sentinel appends a [SENTINEL: ...] notice to that tool result so the model can warn the user and stop relying on the package, but it does not prevent the install.

I won't dress that second one up as prevention. If you need a hard stop before execution on a developer laptop today, SlopScan is also available as a free, open-source local pre-execution hook for Claude Code. Setup is covered in Wiring SlopScan into Claude Code: a skill, a hook, and a bug I almost shipped.

SlopScan package scanning is a Pro-and-up feature, toggled in Dashboard → Settings.

What it looks like (illustrative)

Say your orchestration layer takes the agent's proposed plan and scrubs it before executing anything:

import httpx

plan = "I'll set this up with `npm install @example-scope/legacy-mcp-server` and wire it in."

resp = httpx.post(
    "https://api.sentinelaifirewall.com/v1/scrub",
    json={"content": plan, "tier": "standard"},
    headers={"X-Sentinel-Key": "sk_live_..."},
)
result = resp.json()

scan = result["security"].get("package_scan")
if scan and scan["action"] in ("blocked", "flagged"):
    # Don't run the install. Surface it to a human or ask the agent to
    # pick a currently maintained alternative.
    raise RuntimeError(f"Package check failed: {scan['hits']}")
Enter fullscreen mode Exit fullscreen mode

And an illustrative response. The package name, scope, and flag are placeholders, not a captured result for any real package:

{
  "security": {
    "action_taken": "clean",
    "threat_score": 0.02,
    "package_scan": {
      "action": "reported",
      "hits": [
        {
          "name": "@example-scope/legacy-mcp-server",
          "ecosystem": "npm",
          "trust_score": 12,
          "risk": "CAUTION",
          "flags": ["deprecated"]
        }
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Note action_taken is clean. The prompt is fine. The package is the problem, which is why package_scan is reported separately from the threat verdict. A naive integration that only reads action_taken would sail right past this. Read both.

The prompt-injection angle

One detail in Glow's finding deserves its own paragraph. The Puppeteer server RCE is exploitable via prompt injection. That means the stale-package problem and the injection problem compound: pick a vulnerable server through stale knowledge, then have injected content from a web page or document steer the agent into triggering the flaw.

That second half is the part Sentinel's other layers are built around. Content that's headed into an agent's context, such as fetched pages, tool outputs, and retrieved documents, can be scrubbed for injection before the model acts on it. It's defense in depth rather than a fix for the vulnerable package itself. Removing the package is the real fix. The injection screening just raises the cost of reaching it while the package is still sitting there.

The one thing to do today

Stop treating "the agent chose it" as equivalent to "someone vetted it." Put a registry-verification step between an agent's proposed package and the install command, and make it fail closed.

Concretely, pick one:

  • Route proposed package names through /v1/scrub before executing installs, and gate on package_scan.action.
  • Or install the open-source local SlopScan pre-execution hook for Claude Code so the check happens on the machine, before the command runs.

And audit what your agents have already installed. Grep your developers' MCP configs for the archived reference servers. Glow's numbers (17M+ downloads since July 2025) suggest you'd be in crowded company.

If you want to put the scrub-and-verify step in front of your agents, start at sentinelaifirewall.com. The Starter tier is free with no credit card, and SlopScan package scanning is available on Pro and above.

Source: Glow Labs, "MCPhantom: AI coding agents are installing vulnerable, deprecated MCP servers from training data"

Sources


AI-assisted draft or imaging, human-curated, reviewed and edited.

Top comments (0)