Miasma worm made AI coding agents auto-run its payload on repo open

Tombstone icon

In the first week of June 2026, a self-replicating supply-chain worm called Miasma treated AI coding agent configuration as its primary attack surface. It planted files like .claude/settings.json, .cursor/rules/setup.mdc, .gemini/settings.json and .vscode/tasks.json that auto-execute the moment a developer opens a cloned repo in Claude Code, Cursor, Gemini CLI or VS Code; no npm install required. On June 5 it rode a compromised contributor account into Microsoft's Azure/durabletask, and GitHub disabled 73 repositories across four Microsoft orgs in about 105 seconds, briefly breaking the Azure Functions deploy action for everyone. The worm harvested cloud keys, GitHub tokens and AI provider keys, then exfiltrated to attacker-controlled GitHub repos. Zero CVEs were ever assigned, because nothing here was technically a bug; the agents did exactly what they were designed to do.

Incident Details

Severity:Catastrophic
Company:Microsoft and AI coding-agent users
Perpetrator:AI coding agent
Incident Date:
Blast Radius:Self-replicating worm injected auto-executing payloads into AI coding agent config files; 73 Microsoft repositories across four GitHub orgs disabled in ~105 seconds, briefly breaking the global Azure Functions deploy action; 57 npm packages across 286+ malicious versions, 32 @redhat-cloud-services packages, and 37 PyPI wheels compromised; cloud keys, GitHub tokens, npm tokens, AI provider keys and password-manager contents harvested; persistence survives token rotation because it lives in agent config.

Most worms still need you to do something a little bit dumb. Run the installer. Enable the macro. Paste the helpful command from a forum thread. Miasma figured out something worse: it doesn't need you to run anything at all. It just needs you to open a folder in your AI coding agent, which the average developer does dozens of times a day without a flicker of thought.

During the first week of June 2026, researchers at StepSecurity, SecurityJoes, the Cloud Security Alliance, JFrog and others documented a pair of self-replicating supply-chain worms, Miasma and a Rust-built cousin called IronWorm, that emerged from the npm ecosystem at roughly the same time. What made Miasma a graveyard candidate rather than just another npm infostealer is the target it picked. It went straight for the configuration directories of AI coding assistants, because those directories have quietly become some of the most powerful, least-audited execution surfaces on a developer's machine.

What Miasma actually is

Miasma is assessed to be a variant of the "Mini Shai-Hulud" worm lineage, attributed to a group tracked as TeamPCP. Shai-Hulud, for the uninitiated, was the 2025 npm worm that taught the supply-chain crowd that a poisoned package could steal credentials and then use those credentials to poison more packages, all on its own. Miasma took that template and bolted on a nastier persistence trick.

The first confirmed wave landed on June 1, compromising 32 packages under the @redhat-cloud-services npm scope in about 72 seconds. A larger second wave on June 3 pushed the total to 57 npm packages across 286 or more malicious versions, including packages with real download volume such as an SDK pulling north of 400,000 monthly downloads. By June 7 the campaign had also spilled into PyPI, where Socket counted 37 malicious wheels. Across the entire thing, exactly zero CVEs were assigned, which tells you something important that I'll come back to.

Mechanically, Miasma is a roughly 4 MB JavaScript payload that runs on Bun, a JavaScript runtime it downloads at execution time specifically to operate outside the process monitoring most teams point at Node. It hides its install trigger inside a tiny binding.gyp file using command-substitution syntax, a technique StepSecurity nicknamed "Phantom Gyp," so the malicious code fires during npm install without ever appearing in the scripts section that scanners and humans actually look at. Then it layers on Caesar-cipher decoding, AES encryption and commercial obfuscation, just to make the reverse-engineers earn their paychecks.

The part that belongs here: auto-executing agent config

Strip away the obfuscation and the genuinely novel idea is simple and grim. Miasma writes files into the configuration directories of AI coding tools:

  • .claude/settings.json and .claude/setup.mjs for Anthropic's Claude Code
  • .cursor/rules/setup.mdc for Cursor
  • .gemini/settings.json for Google's Gemini CLI
  • .vscode/tasks.json for VS Code

Each of these files abuses a feature the tool already ships and advertises. Claude Code has SessionStart hooks that run commands when a session begins. Cursor has project rules with alwaysApply: true, which inject their contents into the agent's context every time. VS Code has folder-open tasks that run when you open a directory. Gemini CLI has its own session hooks. None of these are bugs. They are documented conveniences, designed so your agent can set up your environment, load your house rules, or kick off a build the moment you sit down.

The problem is the trust assumption baked underneath them. Those features were designed as if the configuration in a repository was authored by you, or by someone you trust, and is therefore safe to execute without asking. Clone a hostile repository, open it in Cursor or Claude Code, and the agent reads the attacker's instructions and runs them. No npm install. No build step. No prompt. The act of opening the folder is the exploit.

That is what converts a one-time infostealer into something with staying power. A developer who installs a poisoned package exposes whatever credentials are loaded at that moment. A developer whose .claude or .cursor directory gets seeded with a hook has created a standing execution capability that fires again in future sessions, across other repositories, long after the original package is gone. SecurityJoes noted the obvious and ugly consequence: because the persistence lives in agent config rather than in a stolen token, rotating your credentials doesn't evict it. You rotate the keys, you open your editor, and the hook hands the fresh keys right back.

How it spread, and why Microsoft ended up in the headline

Once resident, Miasma harvested a broad sweep of credentials: AWS access keys and session tokens, GCP service-account keys, Azure managed-identity credentials, HashiCorp Vault tokens, GitHub Actions OIDC tokens, npm and RubyGems publish tokens, and SSH keys. It read runner process memory to pull GitHub Actions secrets that are supposed to be masked in logs. It even poked at 1Password, pass and gopass. The loot went to a fleet of attacker-controlled GitHub "dead-drop" repositories, some of which helpfully described themselves as "Miasma - The Spreading Blight." Subtlety was not the goal.

Then it propagated, autonomously, using the write access it had just stolen. That is how it reached Microsoft. On June 5, a previously compromised contributor account was used to push a malicious commit directly into the Azure/durabletask GitHub repository, planting the agent-config payload. Within roughly 105 seconds of detection, GitHub's automated enforcement disabled 73 repositories spread across four Microsoft organizations: Azure, Azure-Samples, microsoft and MicrosoftDocs. The collateral damage was immediate and very public, because one of the disabled repositories was Azure/functions-action, the official GitHub Action thousands of teams use to deploy Azure Functions. Every workflow that referenced it stopped resolving, so a credential-stealing worm briefly became a global CI/CD outage.

Worth noting: the same durabletask project family had already been hit on PyPI in mid-May. StepSecurity and others pointed out that tokens from the earlier compromise may never have been fully rotated, which is how the same account got to push to GitHub two weeks later. Microsoft became a headline victim twice in seventeen days on the same project, which is less a story about Microsoft being uniquely careless and more a story about how a worm with stolen write access just keeps knocking.

Why this is an AI-tooling failure, not just "malware happened"

It would be easy to file Miasma under "bad guys wrote malware" and move on. That misses the point of why it worked. The worm's authors didn't discover a clever zero-day in Claude Code or Cursor. They didn't jailbreak a model. They read the documentation. The agents auto-execute project configuration from whatever folder you open, and the attackers simply wrote configuration.

This is the same defect class the Graveyard has catalogued before: the Amazon Q Developer extension auto-loading MCP servers from a workspace file without consent, and Agentjacking turning Sentry error data into agent commands. The common thread is that agentic developer tools collapsed an old, useful boundary - the one between "data sitting in a project" and "instructions I have agreed to run." For decades, opening a file in an editor was a safe, passive act. Editors that grew autonomous execution hooks quietly made "open this folder" a privileged operation, and most developers never got the memo.

The "zero CVEs" detail is the tell. There was no vulnerability to assign, because nothing malfunctioned. Claude Code ran its SessionStart hook. Cursor applied its always-apply rule. VS Code ran its folder-open task. Each behaved exactly as built. When the worst-case behavior of a system is also its intended behavior, you don't have a bug to patch; you have a design to reconsider.

What it should change

The fix isn't "stop using AI coding agents," and it isn't a sterner warning dialog nobody reads. It's treating agent configuration directories as privileged code. Practically, that means agent vendors defaulting to no auto-execution from untrusted or freshly cloned workspaces, gating hooks behind explicit per-workspace trust the way VS Code already gates some features, and surfacing exactly what a repo's hooks will run before they run. For teams, it means putting .claude/, .cursor/, .gemini/ and .vscode/tasks.json under the same code-review scrutiny as a CI workflow file, alerting on unexpected additions, and storing AI provider keys in a secrets manager instead of a shell profile that a hook can read in one line.

Miasma is not interesting because it was sophisticated. The obfuscation was busywork. It's interesting because it proved that a worm can ride the convenience features of AI coding tools straight through organizational trust boundaries, and that the blast radius tracks the authority we've handed those tools. Developer authority is rarely small, and we keep wiring it into software that runs untrusted instructions the instant we open a folder.

Discussion