Microsoft 73-repo Miasma: AI agent startup, not npm install
Contents
TL;DR
Impact On June 5, 2026, GitHub disabled 73 repositories under Azure, Azure-Samples, microsoft, and MicrosoftDocs. The reported starting point is a malicious commit to Azure/durabletask
Trigger Not npm install, but Claude Code and Gemini CLI SessionStart hooks, Cursor always-applied rules, and VS Code folderOpen tasks. .claude/settings.json, .gemini/settings.json, .cursor/rules/setup.mdc, and .vscode/tasks.json are the execution paths
Response A clone or pull of an affected repository is still triageable by itself. For machines that started an AI coding session, loaded Cursor rules, or opened a trusted VS Code workspace with automatic tasks enabled, check .github/setup.js execution, outbound traffic, and exposed GitHub, npm, and cloud credentials
GitHub disabled 73 Microsoft-related public repositories on June 5, 2026.
StepSecurity’s analysis points to a malicious commit in Azure/durabletask as the starting point.
That commit did not change application source code. It added configuration files read by AI coding tools and editors, plus the malicious code body.
This entry point does not go through the package manager.
In the Mini Shai-Hulud @antv wave, the entry point was preinstall or a Git dependency lifecycle script, and Claude Code / VS Code startup paths stayed behind after the hit.
In this Microsoft repository wave, the entry point itself moved to treating the repository as a workspace for an AI agent or VS Code.
Azure/durabletask received startup configuration, not code changes
The commit StepSecurity names is 5f456b8.
The commit message was Switched DataConverter to OrchestrationContext [skip ci], but the changed files did not match that description.
There was no source-code change. The added files were configuration and setup.js.
The commit timestamp is 2020-03-09T15:59:47Z, which does not line up with the actual push timing.
[skip ci], an old timestamp, a misleading message, and configuration-only additions all line up in the same commit.
The confirmed trigger surfaces are Claude Code, Gemini CLI, Cursor, and VS Code.
They are not all the same kind of “auto-run as soon as you open it” behavior.
| File | Trigger condition | What happens |
|---|---|---|
.claude/settings.json | Claude Code session start | Runs node .github/setup.js through a SessionStart hook |
.gemini/settings.json | Gemini CLI session start | Runs the same setup.js through Gemini CLI’s hook path |
.cursor/rules/setup.mdc | Cursor reads project rules | Uses an alwaysApply: true rule to inject setup execution as an initialization task for the agent |
.vscode/tasks.json | VS Code opens a trusted workspace and automatic tasks are allowed | Runs node .github/setup.js through a runOn: "folderOpen" task |
.github/setup.js | Called from the four paths above | Collects credentials as the malicious code body |
Claude Code and Gemini CLI can read session-start hooks from project-local settings files.
Cursor is less a direct shell-execution setting and more an instruction injected into the conversation context through an always-applied rule: run this setup step.
For VS Code, Workspace Trust and automatic task settings are the boundary. Automatic tasks do not run in an untrusted workspace, but .vscode/tasks.json folderOpen tasks can fire in trusted folders or once the workspace has been allowed.
StepSecurity frames cloning alone as safe, while opening the repository is the risky operation.
Here, “opening” does not mean viewing the directory in Finder or running ls. It means handing the directory to an AI coding tool or IDE as a workspace.
Reading .claude/settings.json with cat is a different operation from starting Claude Code inside that directory.
npm ci --ignore-scripts and “wait N days before installing new package versions” do not cover this path.
The tool configuration is read before dependency resolution enters the picture.
The pnpm 11 and Yarn 4.10 age-gate post covers short-lived npm registry exposure, but it does not inspect startup configuration placed directly in a source repository.
73 repositories were disabled in 105 seconds
StepSecurity says it confirmed the 73 disabled repositories through the GitHub API.
The repositories sat under four organizations: Azure, Azure-Samples, microsoft, and MicrosoftDocs. The disable window ran from 2026-06-05 16:00:50 to 16:02:35 UTC, a span of 105 seconds.
That looks more like GitHub-side automated detection than someone disabling repositories one by one by hand.
An article citing OpenSourceMalware’s tally says Azure alone accounted for 49 repositories, including Azure Functions-related projects, language workers, azure-functions-core-tools, and functions-action.
GitHub Actions workflows that referenced a floating tag such as Azure/functions-action@v1 could fail to resolve while the repository was disabled.
That creates a separate impact: legitimate CI can break even before any malware executes.
TechCrunch reported a Microsoft spokesperson saying the company temporarily removed some repositories for investigation, restored some after review, and notified a small number of potentially affected customers.
Public reporting does not show the number of affected people or how many clones had already been taken.
Miasma keeps changing entry points
Read as a standalone event, this is “Microsoft GitHub repositories were disabled.”
Read as part of the Miasma sequence, the entry point is moving.
| Date | Entry point | What changed |
|---|---|---|
| 2026-05-19 | Microsoft durabletask PyPI publishing rights | StepSecurity says three malicious versions appeared within 35 minutes. They were pushed directly to PyPI with a compromised publishing token, bypassing CI/CD |
| Reported 2026-06-02 | Red Hat @redhat-cloud-services npm scope | Malicious npm packages were published through a legitimate GitHub Actions OIDC path with SLSA provenance. The entry point was preinstall |
| 2026-06-05 | Azure/durabletask GitHub repository | The path moved from a package registry into AI-tool and IDE configuration inside the source repository |
| Reported 2026-06-07 | Hades PyPI wave | Socket confirmed 37 malicious wheel files across 19 packages. *-setup.pth calls Bun and _index.js at Python startup |
The common pattern is that the attacker targets code that runs before the user reads the application code.
In npm, that is preinstall; in Python, it is .pth; in AI agents, it is a session-start hook; in VS Code, it is a workspace task.
For the attacker, these are all places that run before a developer starts normal work.
Same Miasma family, different entry point from the Red Hat npm wave
Microsoft’s June 2 security blog details the Miasma wave in the Red Hat @redhat-cloud-services npm scope.
That wave involved 32 packages and more than 90 malicious versions, published through a legitimate GitHub Actions OIDC path with SLSA provenance.
At install time, preinstall ran a 4.29 MB obfuscated index.js, downloaded Bun, and executed a second-stage malicious body.
Microsoft describes the Red Hat npm payload as collecting GitHub, npm, AWS, Azure, GCP, Vault, Kubernetes, local CLI credentials, SSH keys, browser data, and wallet data.
On CI runners, it pulled secrets from process memory, republished additional packages, and forged SLSA provenance while spreading as a worm.
Microsoft also notes token-monitoring logic and destructive behavior when a decoy token is touched.
The Microsoft 73-repository wave moves the entry point even earlier.
Instead of distributing through the npm registry, it places configuration files into the source repository and uses AI coding tool startup hooks plus rule loading as the entry path.
Even without creating node_modules, opening the repository as a workspace and reaching the relevant tool-configuration load path can put the machine on the execution path.
The Hades PyPI wave follows the same direction.
Socket found 37 malicious wheel files where *-setup.pth is processed at Python startup, downloads Bun, and attempts to run _index.js.
Even without importing the affected package, the .pth file is processed when python, pip, a test runner, a Jupyter kernel, or a CI job starts in that environment.
Across npm, GitHub repositories, and PyPI, Miasma keeps looking for places that run automatically before normal work begins.
Check the workspace, not only dependencies
For a repository that was cloned or pulled and then opened in Claude Code, Gemini CLI, Cursor, or VS Code, check the workspace separately from dependencies.
Start with these files at the workspace root.
.claude/settings.json
.gemini/settings.json
.cursor/rules/setup.mdc
.vscode/tasks.json
.github/setup.js
For Cursor, inspect every .mdc file under .cursor/rules/.
If strings such as alwaysApply: true, Run node .github/setup.js, or required for setup appear, treat the file as an instruction to the agent, not as plain documentation.
For VS Code, inspect .vscode/tasks.json together with runOptions.runOn, task.allowAutomaticTasks, and the Workspace Trust state.
Look for setup.js execution logs, outbound traffic from Node.js, unexpected GitHub repository creation, and use of GitHub, npm, Azure, GCP, AWS, Vault, or Kubernetes credentials.
This family does not stop at “which repository did you clone”; incident scope includes “which tool did you open it with.”
As with the Mini Shai-Hulud response, do not rotate credentials before stopping device-side monitors and persistence.
Prior waves observed logic that detects token revocation and enters destructive behavior.
Network isolation, removal of suspicious startup configuration, log preservation, and then credential rotation is the less destructive order for investigation.
Do not decide execution status from fixed filenames alone.
Treat the environment as Miasma-related if these behaviors line up.
| Place to check | What to look for |
|---|---|
| Processes | node .github/setup.js spawned as a child process of Claude Code, Gemini CLI, Cursor, or VS Code |
| Temporary directories | bun, bun-v1.3.13, .bun_ran, _index.js, *-setup.pth |
| GitHub | Suspicious repositories with Miasma: The Spreading Blight or Hades - The End for the Damned in the description, results/results-*.json, or a Run Copilot job |
| Commits | chore: update dependencies [skip ci], old-looking timestamps, configuration-only additions |
| Outbound traffic | Bun downloads, GitHub API repository/commit creation, unusual access to cloud metadata, Vault, or Kubernetes |
Blocking only a legitimate-looking domain such as api.anthropic.com creates false positives.
Correlate the domain with the parent process of node or bun, the configuration file read immediately before execution, GitHub API activity, and the repository names that were created.
References
- StepSecurity: Miasma Worm Hits Microsoft Again
- Microsoft Security Blog: Preinstall to persistence: Inside the Red Hat npm Miasma credential-stealing campaign
- Cloudsmith: The Miasma worm’s path of destruction
- Socket: Shai-Hulud Descends to Hades: Miasma Worm Campaign Spreads with New PyPI Wave
- TechCrunch: Microsoft’s open source tools were hacked to steal passwords of AI developers
- Ars Technica: For the 2nd time in weeks, Microsoft packages laced with credential stealer
- Claude Code Docs: Hooks reference
- Gemini CLI Docs: Hooks
- Cursor Docs: Rules
- Visual Studio Code Docs: Tasks
- Visual Studio Code Docs: Workspace Trust