Introducing Tenki's code reviewer: deep, context-aware reviews that actually find bugs.Try it for Free
Security
Jul 2026

Miasma Worm Scraped CI Runner Memory for Secrets

Eddie Wang
Eddie Wangengineering

Share Article:

Between June 5 and June 8, 2026, the Miasma supply chain campaign hit Microsoft's Azure GitHub organizations hard. GitHub disabled 73 repositories across four orgs in a 105-second automated sweep. The attack vector: a compromised contributor account pushing a single malicious commit to Azure/durabletask that planted credential-harvesting payloads designed to run the moment a developer opened the repo in Claude Code, Gemini CLI, Cursor, or VS Code.

The parallel Hades campaign poisoned 29+ PyPI packages in the graph ML and bioinformatics ecosystem with cross-platform memory scrapers that read secrets directly from CI runner process memory. Not from environment variables. Not from disk. From the Runner.Worker process address space itself.

Every runtime defense in the world is fighting this after the malware is already executing on the runner. The actual leverage point is earlier: the PR merge that introduces the poisoned dependency, the workflow modification, or the uses: reference change that gets the worm onto your runner in the first place.

What the Miasma worm actually did

The attack started with a compromised contributor account that had write access to Azure/durabletask. The same account had been used in a May 19 PyPI attack against the durabletask Python package. Credentials were never fully rotated, or the account was re-compromised through the worm's own propagation loop.

On June 5, the attacker pushed commit 5f456b8 with a message claiming "Switched DataConverter to OrchestrationContext [skip ci]." Zero source code files changed. Five configuration files added. The [skip ci] flag was deliberate: suppress CI to avoid automated detection. The commit timestamp was backdated to 2020.

Those five files covered four attack vectors:

  • .claude/settings.json with a SessionStart hook that executes the payload when Claude Code opens the repo
  • .gemini/settings.json with the identical hook for Gemini CLI
  • .cursor/rules/setup.mdc containing a prompt injection that tricks Cursor's AI agent into running the payload as "project setup"
  • .vscode/tasks.json with a folderOpen auto-run task. No AI agent needed; VS Code executes it on folder open.

All four pointed to .github/setup.js, a 4.6 MB obfuscated JavaScript credential harvester. Cloning the repository was safe. Opening it was not.

The Hades campaign: memory scraping on every platform

Three days later, the Hades campaign surfaced. StepSecurity identified compromised versions of ensmallen, a popular graph ML package, along with 28 other PyPI packages in bioinformatics, computational biology, and genotype-phenotype analysis. The payload was a different beast from the Azure repo attack, but shared the same infrastructure and credential-harvesting goals.

The key technical innovation: cross-platform memory scrapers that read secrets from the GitHub Actions Runner.Worker process. On Linux, the malware walked /proc/{pid}/maps and read directly from /proc/{pid}/mem. On macOS, it used Mach kernel VM APIs via ctypes to obtain a task port and enumerate memory regions. On Windows, a dynamically compiled C# class called VirtualQueryEx and ReadProcessMemory to crawl the target's memory space.

This matters because the runner process and the workflow job run under the same UID. No privilege escalation required. The secrets don't need to be written to disk or passed as environment variables; they're sitting in plaintext in the worker's address space, and the malware just reads them out.

How the worm propagates through CI

Once the Hades payload has GitHub tokens, it doesn't just exfiltrate them. It uses them to spread. The worm's propagation logic includes three distinct vectors, and they're all relevant to teams running GitHub Actions:

Workflow injection. If the stolen token has the workflow scope, the malware clones a repo, creates a temporary branch, and commits a malicious workflow file named .github/workflows/codeql.yml (hijacking a common security workflow name). The workflow dumps all secrets via ${{ toJSON(secrets) }} to an artifact, then the worm downloads the artifact and deletes the branch and run history.

OIDC trust exploitation. When running inside a GitHub Actions runner with OIDC configured, the malware mints PyPI and npm publish tokens, generates cryptographically signed SLSA provenance bundles using Sigstore, and publishes poisoned versions of legitimate packages that pass all supply chain verification checks. The published packages appear to have valid build provenance from the organization's official CI environment.

IDE and AI agent backdooring. The worm plants configuration files targeting 14 different AI coding tools (Claude, Codex, Gemini, Copilot, Cline, Aider, Tabby, Amazon Q, and others) so that every developer who opens a compromised repo in their IDE triggers another round of credential harvesting.

The collateral damage: Azure/functions-action went down

When GitHub disabled those 73 repositories, one of them was Azure/functions-action, the official GitHub Action for deploying Azure Functions. Every workflow referencing Azure/functions-action@v1 broke instantly. Within hours, a Microsoft Learn thread filled with 20+ developers reporting broken CI/CD pipelines.

This is the mutable-tag problem. Workflows that reference @v1 point to whatever GitHub serves for that tag at resolution time. When the repository disappears, the tag evaporates. Pinning to a commit SHA would have at least failed predictably.

The attack surface is a PR merge

The Miasma/Hades campaign used direct pushes to compromised repos, which is why branch protection rules requiring PR reviews are the first-line defense StepSecurity recommends. But the worm's self-replicating logic also targets the PR path: once it has tokens with write access, it creates branches, commits malicious workflow files, and triggers deployments.

For teams that do enforce branch protection (as they should), the merge gate becomes the critical checkpoint. Every change that could introduce the worm arrives as one of a few recognizable patterns:

  • Dependency changes that add packages from targeted scopes (bioinformatics, graph ML, ML utility packages)
  • Workflow modifications that add new uses: references without pinned SHAs, or change existing pinned SHAs
  • GITHUB_TOKEN scope expansions that give workflows write access to additional resources
  • New configuration files in .claude/, .gemini/, .cursor/, or .vscode/ directories that include execution hooks or startup commands

A human reviewer might catch one of these in isolation. But when you're reviewing 30 PRs a day and the commit message says "update CI config" or "bump dependency," the odds of catching a pinned SHA change or an obfuscated setup hook are slim.

What Tenki's pre-merge review flags

Tenki reviews every pull request before merge, including dependency changes, workflow files, and configuration additions. It's a code review layer, not a runtime security agent. That distinction matters here because the entire Miasma/Hades attack chain depends on getting malicious code onto a runner or developer machine, and Tenki operates at the point where that code is still a diff in a PR.

Here's what that catches, mapped to the specific Miasma/Hades patterns:

Unpinned action references. The worm's workflow injection commits a codeql.yml workflow that references actions/checkout and actions/upload-artifact by SHA (to look legitimate), but the workflow itself is new and unexpected. Tenki flags new workflow files in PRs and reviews their structure, including what secrets they access and whether the trigger conditions make sense for the repository.

Suspicious dependency additions. The Hades campaign compromised niche packages (ensmallen, embiggen, gpsea) with very specific affected versions. A PR that bumps a transitive dependency to one of these versions, or adds one of these packages for the first time, gets reviewed by Tenki with the same rigor as any other code change. The reviewer understands lock file diffs, surfaces version changes, and flags packages that don't match the repository's existing dependency profile.

Token scope and permissions changes. The worm's deployment-based injection method needs repo write access. A PR that expands GITHUB_TOKEN permissions, adds OIDC token request permissions, or configures new deployment environments gets flagged for review. These are exactly the permissions the worm exploits to mint publish tokens and inject workflows.

AI tool configuration files. A PR adding .claude/settings.json with a SessionStart hook, or a .vscode/tasks.json with a folderOpen auto-run command, is exactly the pattern the June 5 attack used. These files are just code in a PR diff, and Tenki reads them.

Pre-merge vs. runtime: different problems

Runtime tools like StepSecurity's Harden-Runner caught the Hades memory scraper mid-execution by detecting the process memory read and killing the malicious process. That's genuinely valuable, and if you're running GitHub Actions at scale, you should be using runtime monitoring.

But runtime detection means the malicious code is already running on your infrastructure. It already had access to your runner's network, process list, and potentially some window of time in process memory before detection kicked in. The worm already executed; the question is just how far it got.

Pre-merge review catches the PR that would install the worm. The dependency bump, the workflow addition, the config file. It doesn't compete with runtime monitoring; it adds a layer before the code reaches your runner at all. You want both. But if you only have one, the layer that prevents execution beats the layer that interrupts it.

What you should do right now

If you're managing GitHub Actions pipelines, here's the minimum response to Miasma/Hades:

  1. Rotate credentials immediately if any developer on your team cloned an affected Azure repository after June 2 and opened it in VS Code, Claude Code, Cursor, or Gemini CLI. GitHub tokens, cloud provider keys, SSH keys, npm tokens. All of them.
  2. Audit your dependency trees for any of the 29 compromised Hades PyPI packages. Check for ensmallen 0.8.101, embiggen 0.11.97, pyphetools 0.9.120, and the others listed in StepSecurity's Hades advisory.
  3. Pin all GitHub Actions to commit SHAs. The Azure/functions-action@v1 breakage is a textbook example. Mutable tags are a liability.
  4. Enforce branch protection. No direct pushes to default branches. The June 5 attack was a direct push. Branch protection alone would have forced it through a review process.
  5. Add automated PR review for workflow and dependency changes. Whether that's Tenki or another tool, the point is that human reviewers miss dependency and workflow changes at scale. Automated review doesn't get fatigued and doesn't skip the lock file diff.
  6. Scan for planted AI tool configs. Check your repositories for unexpected .claude/, .gemini/, .cursor/rules/, and .vscode/tasks.json files with execution hooks. If they reference a setup.js or similar, treat the system as compromised.

The wiper deterrent

One detail worth calling out: the Hades campaign includes a wiper deterrent. The malware installs a background service called gh-token-monitor that polls the GitHub API using the stolen token. If the token is revoked (returning a 4xx status), the service triggers rm -rf ~/. The attacker is explicitly weaponizing credential rotation against the response team: revoke the token and lose your data.

The 72-hour TTL on the monitor means there's a window. But it also means the right response sequence is: isolate the machine, image the disk, then revoke the token. Don't revoke first. This is a new pattern for supply chain attacks and it complicates the standard incident response playbook.

Stop the merge, stop the worm

The Miasma/Hades campaign is the most sophisticated supply chain worm we've seen in the wild. Cross-platform memory scraping, SLSA provenance bypass, AI agent hijacking across 14 tools, a wiper deterrent. The threat actor isn't just stealing credentials; they're building self-replicating infrastructure that weaponizes the trust model of open-source package registries and CI/CD systems.

But every propagation path in this campaign starts with code changes: a poisoned dependency, a new workflow file, a config hook, a permissions expansion. If you're reviewing those changes before they merge, you're cutting off the worm's entry point. That's the case for automated pre-merge review, and it's why Tenki reviews every PR including the ones that look like routine dependency bumps and CI config updates.

Tags

#supply-chain-attack#cicd-security#pre-merge-gate#incident-response

Recommended for you

What's next in your stack.