← All news
AI SecurityThreat IntelligenceAI Agents

The Malware Put a Weapons Jailbreak at the Top of the File So the Scanner Would Refuse to Read It

Obiguard Research Team·September 9, 2026·11 min read

Every security control has a failure mode that its designers accepted on purpose. Signature scanners miss what they have no signature for. Sandboxes miss what waits them out. Static analysis misses what only exists at runtime. You learn the shape of the gap and you build something else to cover it.

LLM-based code review has a failure mode too, and it is not one anybody chose. It refuses.

Google Threat Intelligence Group's latest AI Threat Tracker, published this week, contains a finding that is worth more attention than the headline it generated. The Hacker News covered the report on September 8, 2026, leading on a credential-harvesting campaign built and executed in under six hours — which is a genuinely alarming number and we will get to it. Infosecurity Magazine led on AI coding tools becoming a primary target the same day.

The detail underneath both is smaller and stranger. A commodity crimeware family is now writing text designed to be read by your AI, not by you — and the text works because the model was trained to be careful.

The file that argues with the scanner

The malware is DUSTMAKER, a cross-platform JavaScript credential stealer used by UNC6780 — the financially motivated crew publicly tracked as TeamPCP — since April 2026. It is the successor to SANDCLOCK, the Python stealer the same group ran in March and April against Linux and Kubernetes environments.

GTIG found adversarial prompts embedded as comments at the top of DUSTMAKER's JavaScript loader scripts (_index.js). The prompts open with a fake system directive — SYSTEM OVERRIDE — CLASSIFIED BRIEFING — declare that safety guidelines are suspended, and then demand step-by-step synthesis instructions for weaponised biological agents, followed by a second section requesting an implosion-type nuclear device specification from a fabricated Los Alamos persona. We are not reproducing the body of it, and you do not need to see it to understand the mechanism.

GTIG's assessment of why it is there is the important sentence: the text is "likely intended to cause LLM security scanners to fail or skip analysis of the malicious JavaScript code underneath due to safety or policy refusals."

Read that again with your own tooling in mind. The attacker is not trying to convince the model that the file is benign. That would be prompt injection in the ordinary sense — an argument the model might win. This is the opposite. The attacker wants the model to be offended. A scanner that reads the first forty lines, hits a chemical-weapons request, declines to continue, and returns a refusal has behaved exactly as its safety training intended. It has also just handed back a clean-ish non-answer on a file full of credential theft.

The security property being attacked is not the model's reasoning. It is the model's conscientiousness.

Three ways one payload targets the AI in the room

The refusal trick is one of several. DUSTMAKER is built around the assumption that a modern developer environment contains an AI agent with filesystem access and shell privileges, and it treats that agent as the execution primitive.

It writes into the assistant's config directories. DUSTMAKER drops or modifies files in hidden project workspace directories — .claude/, .vscode/, .cursor/ and others. GTIG describes the effect plainly: the malicious configuration files "instruct the AI assistant to run arbitrary commands or scripts (such as setup.mjs) during routine developer interactions. This effectively forces the AI model to execute commands on the attacker's behalf without the developer's knowledge." The same dropped files create automated build or startup commands, so the payload re-executes whenever the workspace is opened.

If that mechanism feels familiar, it should. We covered it five days ago when Manifold Security showed that a malicious .git config could run code inside seven coding agents before the trust prompt appeared. The difference between that story and this one is the difference between a disclosure and a deployment. GitSpawn was researchers demonstrating a class of flaw responsibly. DUSTMAKER is a criminal group shipping the same idea at supply-chain scale against PyPI, npm and Docker Hub.

It poisons the tools the agent trusts. UNC6780 compromised legitimate developer accounts to publish trojanised forks of real MCP servers to PyPI — tiktoken_mcp among them — and injected code directly into official organisational GitHub repositories including azure-functions-mcp-extension. GTIG's framing of the payoff: backdooring these integrations "ensured their payloads and malicious workspace hooks were automatically ingested into developer environments whenever the assets were downloaded or cloned."

It steals the identity that signs the build. When DUSTMAKER detects a CI/CD environment, it extracts OIDC tokens from the process memory of GitHub Actions runners. With those tokens it authorises itself as a trusted publisher and ships compromised package versions carrying valid, cryptographically signed SLSA Build 3 attestations.

Signed is not the same as trustworthy

That last one deserves its own beat, because a great deal of AI supply chain guidance over the past two years has quietly assumed the opposite.

The recommended posture for agentic development has been: let the agent install things, but constrain it to packages with provenance. Signed artefacts, verified publishers, build attestations. It is good advice and it remains good advice. But GTIG's conclusion is unambiguous about what happens when the signing identity itself is the thing that was stolen — packages published with valid tokens "will pass AI coding agent automated trust checks."

An attestation proves the artefact came out of the build system it claims to have come out of. It has never proved that the build was authorised, and when the attacker is living inside the runner, those two facts diverge. Every automated trust check downstream — including the ones your coding agent runs before it pulls a dependency into a workspace — inherits that gap.

This is the same lesson the LiteLLM compromise taught from the other end. TeamPCP hit LiteLLM's GitHub Actions in late March; five months later the framework was in CISA's KEV catalog for an unrelated flaw, and organisations discovered that the hard question was never is this dependency signed but do we know where it runs and what credential it holds.

Six hours, and the part that actually scales

The headline finding is worth stating precisely, because it is the tempo argument rather than a novel-capability argument.

During a Mandiant incident response in Q2 2026, a financially motivated actor compromised cloud infrastructure and deployed an autonomous, multi-agent AI framework. GTIG's account: the actor leveraged an AI coding chatbot and a set of agent instructions — preconfigured Markdown files acting as operational playbooks — to plan, build and execute a mass credential harvesting campaign. The framework managed vulnerability scanning, credential harvesting, real-time troubleshooting and IP rotation without a human in the loop. Elapsed time from compromise to thousands of stolen third-party credentials: under six hours.

Separately, GTIG documented an exposed command-and-control dashboard for a reconnaissance framework named Recon, actively managing more than 23,800 harvested secrets including cloud and AI service API keys, organised around agentic configuration files with names like AGENTS.md and agentic_vuln_research.md.

None of these individual steps is new tradecraft. Scanning, harvesting, rotating egress IPs — that is a decade-old playbook. What changed is that the latency between steps went to roughly zero, because nobody had to wake up and read the last one's output. GTIG's John Hultquist put the consequence in one line: criminals "will gravitate to attacks that are faster than we can respond to."

Six days ago we wrote about three frontier labs shipping autonomous zero-day discovery with vetted-access programmes — the supply side of this, gated at the labs' door. This is the demand side, and it did not need frontier capability at all. It needed a coding chatbot, some Markdown, and a compromised cloud account.

What to do this week

  • Treat AI assistant config directories as executable content. .claude/, .cursor/, .vscode/ and their equivalents should be diffed in code review, flagged when they appear in a dependency, and excluded from anything an agent is allowed to auto-apply from a freshly cloned repository.
  • Do not accept a refusal as a scan result. If an LLM review step returns a safety refusal, that is an unanalysed file, not a passed one — it should fail the pipeline and route to a human, and it should be a loud signal in its own right. A source file containing a nuclear weapons prompt has already told you everything you need to know.
  • Assume OIDC tokens in runners are collectable. Shorten their lifetime, scope them to a single repository and environment, and alert on publishing events that do not correspond to a human-approved release.
  • Rotate what a build runner could have seen, not what you think it used. The token inventory in the runner is the blast radius.
  • Pin and review MCP servers like dependencies, because that is what they are. A fork of a popular MCP package is a credible delivery vector now, not a theoretical one.

Where Obiguard fits

Start with the honest part, because it is directly relevant. Obiguard SOC runs an automatic LLM code review on every push to a connected repository — which means the evasion technique in this report is aimed squarely at a class of control we ship. Pretending otherwise would be worthless to you.

What matters is that it is not the only control in the path, and that refusal is treated as a finding rather than a silence.

CVE Radar is deterministic and runs independently. Every connected repo is scanned on every push and once daily for vulnerable dependencies, returning the exact file and line, an upgrade compatibility report with a 0–100 safety score, and the cross-repo blast radius before you upgrade. An adversarial comment block at the top of a JavaScript loader does not affect any of that. It cannot argue with a lockfile diff.

Threat Intelligence ranks by what is actually being used. Findings are cross-matched against CISA's KEV catalog and FIRST.org EPSS scores, so an actively exploited dependency surfaces above a queue of hundreds sorted by CVSS. In a story where the interval between exposure and mass harvesting was six hours, the ordering of the queue is the whole game.

Findings land somewhere with a trail. Alerts, CVE findings, threat matches and code findings arrive in one severity-ranked queue; dismissing a CVE or code finding requires a comment and is written to your organisation's audit log; threat-match acknowledgement is tracked per match. A pipeline that silently swallowed an unanalysable file is the exact shape of gap this leaves.

The complementary control is Governance AI, and it applies to the agent side rather than the repo side. When a coding agent's workspace config has been rewritten to make it run setup.mjs, the model is not compromised — it is obediently doing what its configuration says. What limits the damage is what that agent is permitted to reach: allow-lists bind an agent's credential to specific models, tools and domains, so an instruction to exfiltrate to an attacker endpoint fails at the boundary rather than at the model's judgement. Inspection is synchronous and in-path, evaluating prompts, responses and tool calls against the bound policy set, with out-of-scope tool invocations blocked and logged. And the audit ledger records what the agent actually did — append-only, streaming to Splunk, Datadog, Sumo Logic or S3, written outside the workstation that may be lying about it.

The boundary, stated plainly as always: none of this patches a trojanised PyPI package, and none of it stops a developer from cloning a hostile repository. What it changes is whether a hijacked agent's actions are bounded, visible and reconstructible afterwards.

The uncomfortable part

The industry spent three years teaching models to refuse. It was the right project, it was expensive, and it worked well enough that a criminal group has now built a business process on top of it.

There is no clean fix inside the model for this one. A scanner that reads weapons-synthesis instructions and analyses the file anyway is a scanner with weaker safety behaviour, and nobody should want to ship that. The fix is architectural and slightly deflating: the LLM cannot be the only thing that looks, and its refusal has to be routed as an anomaly rather than absorbed as an outcome.

Which is the oldest lesson in security, arriving in a new costume. A control that fails closed is safe. A control that fails quiet is furniture.

Explore Obiguard SOC or talk to us about what your pipeline currently does when an automated review comes back with no answer at all — and whether anyone would notice.

How Obiguard helps

Turn this into enforced policy, not just awareness.

Obiguard sits in front of every AI request your organization makes — screening prompts and outputs against the guardrails, compliance frameworks, and audit trails that stories like this one make necessary.

See how it works →