Every dependency in your pipeline is a stranger you agreed to run as root. This week Google's Threat Intelligence Group put a name on the strangers who now show up with agents in tow, and the news is worse than "attackers are experimenting with AI".
In a follow-up to its May 2026 report on adversarial misuse of AI, GTIG lays out what changed between prompting and autonomy. The headline observation from Q2 2026: one actor compromised a cloud resource and then planned, built and executed an agent-driven mass credential harvesting campaign in under six hours. Six hours. From foothold to fleet.
The one paragraph a CI/CD owner has to read
GTIG describes a credential stealer they call DUSTMAKER, deployed by UNC6780 (also tracked as TeamPCP) as part of a supply-chain campaign running since March 2026 across PyPI, npm and Docker Hub. Two details matter for anyone who ships software:
- DUSTMAKER extracts OIDC tokens directly from the process memory of GitHub Actions runners.
- The compromised package versions ship with valid, cryptographically signed SLSA Build 3 attestations.
Read that again. The provenance that was supposed to be your defence, isn't. The token you thought was ephemeral, isn't (not while a runner is still alive). Signed. Verified. Still hostile.
Isn't this just another supply-chain post?
Not quite. What GTIG documents is the moment supply-chain compromise stops being a one-shot backdoor and starts behaving like a persistent tenant inside your developers' IDE.
DUSTMAKER drops files into hidden directories your developers already trust: .claude/, .vscode/, .cursor/. It plants automated build or startup commands so the malware wakes up whenever the IDE or the AI extension opens the workspace. In CI it masquerades as pipeline tasks with names like "Copilot Setup" and, having done its work, issues API calls to delete the workflow execution logs. It targets secrets.json from Cline and config.yaml from Continue AI, which cheerfully store plaintext API keys and custom model routing endpoints for whoever asks first.
Meanwhile, at the registry layer, UNC6780 has been pushing trojanized forks of legitimate Model Context Protocol servers, tiktoken_mcp and azure-functions-mcp-extension among them. Every developer who adds a helpful MCP is now running arbitrary code with the trust level of "I typed my API key in there".
Why the SLSA line matters
SLSA Build 3 was pitched as the level where the build platform, not the developer, vouches for what came out. Attackers signing packages at that level is not proof SLSA is broken. It is proof that a stolen build credential produces a valid attestation, which is exactly what the threat model warned about. If you consume attestations without also pinning the identity that produced them, you have bought a signature and not a guarantee.
The uncomfortable follow-on: OIDC tokens extracted from a live runner will produce genuine, non-suspicious attestations for as long as they are valid. Rotating on a nightly schedule does not help. You need job-scoped, minute-lived tokens, and you need to verify the sub claim, not just the fact of a signature.
Numbers to sit with
- Over 23,800 harvested secrets managed live in a single actor dashboard GTIG calls "Recon", including API keys for cloud and AI services.
- Average per-account price for stolen AI credentials on underground markets more than doubled in 2026, with Claude, Gemini, Cursor Pro and Devin the most-listed targets.
- Coordinated model-distillation campaigns against Google's frontier models exceeding 100 million prompts, rotating queries across thousands of compromised credentials.
The market is telling you where the attackers think the money is. It is inside your CI account, your model provider account, and your coding-agent subscription.
What actually helps
Three things, none of them new, all of them now urgent:
- Treat OIDC token lifetime as an attack surface. Job-scoped tokens with
audandsubchecks on the consumer side. If your workflow currently runs with a token good for the whole job, assume any process on that runner can lift it. - Pin MCP servers and IDE extensions the way you pin base images: by digest, from an internal mirror, reviewed on upgrade. Something like
mcp-server@sha256:<digest>from$REGISTRY, notlatestfrom a public registry. If your developers install MCPs by name from the open internet, you already lost. - Diff attestations against the identity that produced them, not just their presence. A valid SLSA line above a subject you have never seen before is not a pass. Store the expected signer per package and alarm on drift.
Google's answer inside its own perimeter is a stack it calls AI Threat Defense, with a model it names Gemini 3.8 Flash Cyber as the reasoning engine and Wiz feeding risk context. Fine for Google. For the rest of us, the report is not an announcement, it is a checklist. Print the DUSTMAKER indicators. Rotate what you can. Assume the rest is already in your workspace.
Six hours from foothold to fleet. The next one will be four.
Top comments (1)
The SLSA paragraph deserves the uncomfortable follow-on it got. I run my own agent fleet on a VPS and the mental shift this report forced for me: provenance answers "who built this," never "who is running it now." A stolen build credential produces exactly the attestation your verifier was told to trust, so the signature is only as fresh as the credential hygiene behind it — which is why the job-scoped, minute-lived token point is the real fix and nightly rotation is theater.
The plaintext config files detail hit closer to home than the registry stuff. Cline's secrets.json and Continue's config.yaml are exactly the files I would never think to enumerate in an incident response plan, because they're "editor config," not infrastructure. Mine now hold no long-lived keys at all — the agents read scoped credentials from an injected env at launch — but I'd bet most setups people run today still have a real provider key sitting in a dotfile that a malicious MCP server can read with plain filesystem access the moment it's trusted.
One thing I keep turning over: you pin the MCP server's identity at install time, fine — but trojanized forks mostly arrive as updates or tempting alternatives ("the maintained fork of tiktoken_mcp"), so pinning has to be re-verified on every change, which is the step everyone skips under time pressure. Do you see any realistic path to making that verification automatic at the package-manager layer, or is this destined to stay a per-developer discipline problem?