The Hades PyPI Campaign: How a Supply Chain Worm Turns Your Build Pipeline Into a Credential Harvester

by R. Demetri Vallejos
securitysupply-chainpypithreat-intelligence

In June 2026, Orca Security published its analysis of the Hades campaign — a coordinated supply chain attack against the Python Package Index that compromised 26 packages containing 37 malicious wheel files. Hades is not a clumsy typosquat that waits for someone to misspell a package name. It is the latest, most capable evolution of the Miasma/Shai-Hulud threat lineage: a self-propagating worm that harvests cloud credentials, spreads using the GitHub tokens it steals, and actively tries to blind the tools sent to investigate it.

This post is a straight technical breakdown — how the attack works, what to look for, and what to do right now if you depend on any of the affected packages. Sources are linked at the end.


What Makes Hades Different

Supply chain attacks against package registries are not new. What separates Hades from the usual install-time setup.py malware is a combination of four things working together:

  1. It executes without an install hook. No malicious setup.py, no post-install script — the payload fires every time the Python interpreter starts.
  2. It is self-propagating. Stolen GitHub tokens are used to poison additional packages, turning every compromised maintainer into a new distribution vector.
  3. It is coercive. A persistence daemon threatens destructive action if its tokens are revoked.
  4. It is counter-forensic. The payload ships prompt-injection text aimed at LLM-based analyzers and sends decoy traffic to confuse network monitoring.

This is a worm with an extortion module and an anti-analysis module bolted on. Treat it accordingly.


The Attack Chain

Stage 1 — The .pth execution trick

Hades's cleverest move is how it achieves code execution. Instead of a malicious install script, each poisoned wheel ships a *-setup.pth file.

.pth files are a legitimate, decades-old Python feature. They live in site-packages and normally just add directories to the import path. But Python's site module also executes any line in a .pth file that begins with import — automatically, every time the interpreter starts. No one has to import the malicious package. No one has to call its functions. Simply having it installed in the environment is enough.

The Hades .pth files contain an obfuscated import hook. When triggered, it bootstraps the next stage.

Stage 2 — Bun as a portable runtime

Rather than rely on the victim having Node.js, the loader downloads the Bun JavaScript runtime (versions 1.3.13 / 1.3.14 were observed) directly from GitHub. Bun is a single self-contained binary, which gives the attacker a consistent cross-platform execution environment on Linux and macOS without touching the system's existing toolchain.

Bun then executes an obfuscated _index.js payload — a bundle of roughly 16 encrypted components that make up the actual malware.

Stage 3 — Aggressive credential harvesting

The payload's primary job is theft. It scrapes process memory and the filesystem across as many vectors as it can reach:

  • Cloud provider tokens — AWS, GCP, and Azure credentials
  • Kubernetes secrets
  • GitHub credentials and tokens
  • SSH private keys
  • Docker registry configurations
  • Shell histories (which routinely leak secrets passed on the command line)

Everything collected is encrypted with a hybrid AES-256-GCM + RSA-2048 scheme and exfiltrated to attacker-controlled GitHub repositories.

Stage 4 — Persistence, propagation, and coercion

This is where Hades stops being a simple stealer:

  • Worm-like spread. Stolen GitHub tokens are reused to publish malicious versions of other packages the victim can write to. The campaign grows itself.
  • A gh-token-monitor daemon watches the stolen GitHub tokens and threatens destructive action if they are revoked — an extortion mechanism designed to discourage exactly the remediation you should be doing.
  • Anti-analysis payloads. The malware embeds prompt-injection text intended to manipulate LLM-based security analyzers reading its code, and sends decoy network traffic to Anthropic's servers to muddy traffic analysis. (To be clear: this is the malware abusing the appearance of legitimate AI traffic as camouflage — not a compromise of any AI provider.)

Affected Packages

Orca attributes 26 packages to the campaign, clustered in two groups. If any of these are in your dependency tree — directly or transitively — treat your environment as compromised until proven otherwise.

Bioinformatics / Graph-ML cluster: ensmallen, mflux-streamlit, nhmpy, ppkt2synergy, embiggen, gpsea, pyphetools

Developer-tooling cluster: bramin, cmd2func, coolbox, dynamo-release, executor-engine, executor-http, funcdesc, magique, magique-ai, mrbios, napari-ufish, nucbox, okite, pantheon-agents, pantheon-toolsets, spateo-release, synago, ufish, uprobe

The targeting is notable: the bioinformatics cluster suggests research and academic environments — exactly the kind of high-trust, often under-resourced infrastructure that holds valuable data and frequently runs with broad cloud permissions.


Indicators of Compromise

Linux persistence:

  • ~/.config/systemd/user/update-monitor.service
  • ~/.config/systemd/user/gh-token-monitor.service
  • Lock files: /tmp/.bun_ran and /tmp/tmp.0144018410.lock

macOS persistence:

  • ~/Library/LaunchAgents/com.user.gh-token-monitor.plist

Filesystem:

  • Any *-setup.pth file in site-packages containing an import line you cannot account for

GitHub:

  • Attacker repository naming patterns: stygian-cerberus-* and tartarean-charon-*
  • Unexpected commits, new workflows, or new repositories under accounts whose tokens may have been exposed

The Defensive Playbook

If you have any exposure, work the problem in this order. Isolate before you rotate — revoking tokens on a still-connected machine can trip the extortion daemon.

  1. Isolate first. Disconnect affected workstations and CI runners from the network before doing anything else.
  2. Remove or pin away from the affected package versions across every environment and lockfile.
  3. Hunt and remove persistence artifacts using the IOCs above — systemd user services, LaunchAgents, lock files, and rogue .pth files.
  4. Rotate every reachable credential, in priority order: GitHub tokens first, then cloud provider keys (AWS/GCP/Azure), then SSH keys and Docker registry credentials. Do not let the gh-token-monitor threat deter you — that is its entire purpose.
  5. Audit your GitHub footprint. Review repositories for unauthorized commits, modified workflows, and new repos matching the IOC naming patterns. Assume any token the worm touched was used to push.
  6. Rebuild, don't clean. For developer workstations and CI runners that executed a poisoned package, rebuild from a known-good image rather than attempting surgical removal.

The Structural Lesson

Hades is effective because it exploits trust that is structural, not accidental:

  • Public registries are implicitly trusted. pip install pulls and runs code from an open registry with the same privileges as your developer or your CI runner.
  • .pth execution is invisible. Most teams have never audited a .pth file in their lives, and most tooling doesn't flag them. Execution that requires no import and no function call sidesteps the mental model of "I didn't run anything malicious."
  • Credentials sit in plaintext, everywhere. Environment files, ~/.aws/credentials, shell history, Docker config — long-lived secrets in predictable locations are exactly what a memory-and-filesystem scraper is built to find.
  • Stolen credentials are indistinguishable from real ones. Once the worm holds a valid GitHub token, nothing downstream can tell its publish from yours. That is what lets it spread.

The recurring theme across the supply chain incidents of the past year is the same: long-lived, unscoped, plaintext credentials that, once stolen, cannot be distinguished from legitimate ones — and provenance that no downstream system actually verifies. Defenses that meaningfully reduce this blast radius look alike regardless of vendor: short-lived and scoped credentials, hardware-backed signing keys, verified build provenance, network egress controls on build environments, and the discipline to rebuild rather than disinfect.

At Aethyr, reducing exactly this kind of blast radius — verifiable identity and signed, scoped authorization for the agents and pipelines that move code and credentials — is core to what we build. But the immediate takeaway needs no product: if you ship Python, audit your dependency tree against the list above today, and treat any match as a credential-rotation event.


Source: Orca Security, "The Hades PyPI Supply Chain Attack". Package lists, IOCs, and technical details are drawn from that report; verify against the original and current advisories before acting, as active campaigns evolve.