Shai-Hulud 'Hades' Campaign — Trojanized PyPI Packages Auto-Execute Bun Credential Stealer via Python Wheel Startup Hooks (*-setup.pth)

Shai-Hulud 'Hades' Campaign (TL-2026-0734), also tracked as Hades, is a critical-severity supply-chain compromise, first published 2026-06-09. It is attributed to TeamPCP with medium confidence, affects PyPI (open-source maintainers) Bioinformatics PyPI packages, maps to 30 MITRE ATT&CK techniques (T1003, T1005, T1021), and is covered by 9 detection rules and 29 indicators of compromise.

Key facts for TL-2026-0734

Threat ID
TL-2026-0734
Also known as
Hades, Hades - The End for the Damned, Shai-Hulud Hades PyPI wave, Miasma PyPI wave
Severity
CRITICAL
Status
ACTIVE
Category
SUPPLY_CHAIN
First published
2026-06-09
Last reviewed
2026-06-09
Attribution
TeamPCP
Attribution confidence
MEDIUM
Motivation
FINANCIAL
Target sectors
technology, software-development, bioinformatics, scientific-research, healthcare, academia, open-source, ai-ml
Target regions
North America, Europe, Global
Detection rules
9
Indicators of compromise
29

Malware and tooling in Shai-Hulud 'Hades' Campaign

Malware and tooling: Shai-Hulud / Hades / Miasma, Bun (bun-v1.3.13 / v1.3.14)

The Shai-Hulud 'Hades' campaign (a PyPI branch of the self-spreading Mini Shai-Hulud / Miasma lineage attributed to TeamPCP) trojanized at least 19 science- and AI-focused PyPI packages (37+ malicious wheels) by shipping a *-setup.pth file that executes at Python interpreter startup — with no package import required — to download the Bun JavaScript runtime and run an obfuscated _index.js credential stealer. The malware harvests GitHub/npm/PyPI/cloud secrets, self-propagates via SSH/SCP and OIDC trust abuse, and exfiltrates to attacker-created GitHub repositories tagged 'Hades - The End for the Damned'.

How Shai-Hulud 'Hades' Campaign works

In June 2026 researchers (Socket, SocRadar, StepSecurity, Endor Labs, JFrog) tracked a new PyPI wave of the self-replicating Shai-Hulud supply-chain worm, branded 'Hades – The End for the Damned' and forming a PyPI branch of the Mini Shai-Hulud / Miasma lineage attributed to the threat actor TeamPCP. The campaign trojanized at least 19 PyPI packages across 37+ malicious wheel artifacts, concentrated on bioinformatics/computational-biology tools (dynamo-release, spateo-release, coolbox, ufish, napari-ufish, ensmallen, embiggen, gpsea, pyphetools, mrbios) and AI/MCP developer tooling (pantheon-agents, magique-ai, langchain-core-mcp, openai-mcp, instructor-mcp, tiktoken-mcp, ray-mcp-server), plus requests/Flask typosquats (rsquests, tlask, rlask).

The defining innovation of the Hades wave is the abuse of Python's site-module .pth processing. Each compromised wheel ships a '*-setup.pth' file; because Python's site module executes any .pth line beginning with 'import' at interpreter startup, the malicious code runs the next time Python starts in the environment — during pip, pytest, a notebook kernel, or any CI job — with NO 'import compromised_package' ever required. This converts a passive, unused dependency into a delayed execution trigger and dramatically increases blast radius on CI runners and developer workstations that routinely create virtualenvs. The loader uses urllib.request and subprocess.run to download a pinned Bun runtime (bun-v1.3.13 / v1.3.14) from the legitimate github.com/oven-sh/bun/releases/download path, writes a '.bun_ran' sentinel, and executes a 4.7–4.8 MB obfuscated JavaScript payload named _index.js. A later mutation split loader and payload — searching across sys.path for the payload and embedding obfuscated code in package __init__.py and native .abi3.so extensions — to evade signature-based detection.

The _index.js stealer is cross-platform and multi-stage. It opens with an adversarial prompt-injection block designed to hijack LLM-based security analyzers ('AI analyst misdirection'). It then runs platform-specific in-memory credential scrapers: reading /proc/{pid}/mem on Linux, using Mach task-port APIs via ctypes on macOS, and dynamically compiling C# (VirtualQueryEx / ReadProcessMemory) via PowerShell on Windows — frequently targeting the GitHub Actions 'Runner.Worker' process to lift GitHub Actions secrets. It harvests credentials for GitHub, npm, PyPI, RubyGems, JFrog, CircleCI, Anthropic, AWS, GCP, Azure, and Kubernetes, plus Docker configs, HashiCorp Vault tokens, SSH keys, shell histories, .env / .npmrc / .pypirc files, and Claude/MCP configuration files. The 16-blob payload is protected with AES-256-GCM (per-blob keys) and hybrid AES-256-GCM + RSA-2048 / RSA-PSS-signed dead-drops.

Command-and-control and exfiltration are GitHub-native: the malware polls GitHub commits for keyword dead-drops ('TheBeautifulSnadsOfTime' for eval payloads, 'firedalazer' for the Python dropper, 'DontRevokeOrItGoesBoom' for encrypted tokens) and exfiltrates collected secrets by auto-creating GitHub repositories whose descriptions read 'Hades - The End for the Damned' (underworld-themed name components stygian, tartarean, cerberus, charon, styx, lethe, thanatos, persephone) and uploading 'format-results'/'results/results-<ts>-<counter>.json' artifacts via a 'Run Copilot' workflow. Outbound data is also disguised as traffic to an invalid Anthropic endpoint, https://api.anthropic.com/v1/api. The worm self-propagates by parsing ~/.ssh/known_hosts and ~/.ssh/config to spread over SSH/SCP, and by abusing developers' OIDC trust to mint Fulcio signing certs, generate SLSA provenance, log to Rekor, and publish trojanized package versions with valid signatures. It establishes persistence via Linux systemd units (update-monitor.service, gh-token-monitor.service) and ~/.local/share/updater/update.py, and macOS LaunchAgents, and hijacks IDE/AI assistant config (.cursorrules, .windsurfrules, .github/copilot-instructions.md). A 'wiper deterrent' (gh-token-monitor) watches token validity over a 72-hour TTL and runs destructive 'rm -rf' commands if a stolen token is revoked, discouraging remediation. The campaign tracker has grown to 471 total artifacts (411 npm artifacts across 106 packages; 60 PyPI artifacts across 37 packages).

MITRE ATT&CK techniques used in TL-2026-0734

Credential Access

T1003 OS Credential Dumping; T1528 Steal Application Access Token; T1552 Unsecured Credentials; T1555 Credentials from Password Stores

Collection

T1005 Data from Local System; T1056 Input Capture

Lateral Movement

T1021 Remote Services; T1570 Lateral Tool Transfer

Defense Evasion

T1027 Obfuscated Files or Information; T1036 Masquerading; T1140 Deobfuscate/Decode Files or Information; T1497 Virtualization/Sandbox Evasion

Discovery

T1057 Process Discovery; T1082 System Information Discovery; T1614 System Location Discovery

Execution

T1059 Command and Scripting Interpreter; T1204 User Execution

Command and Control

T1071 Application Layer Protocol; T1102 Web Service; T1105 Ingress Tool Transfer; T1573 Encrypted Channel

Initial Access

T1195 Supply Chain Compromise

Impact

T1485 Data Destruction

Persistence

T1543 Create or Modify System Process; T1546 Event Triggered Execution; T1547 Boot or Logon Autostart Execution

Exfiltration

T1567 Exfiltration Over Web Service

Resource Development

T1583 Acquire Infrastructure; T1586 Compromise Accounts; T1608 Stage Capabilities

Affected products and versions in Shai-Hulud 'Hades' Campaign

  • PyPI (open-source maintainers) — Bioinformatics PyPI packages
    Vulnerable versions: dynamo-release 1.5.4; spateo-release 1.1.2; coolbox 0.4.1; coolbox 0.4.2; ufish 0.1.2; ufish 0.1.3; napari-ufish 0.0.2; napari-ufish 0.0.3; ensmallen 0.8.101; embiggen 0.11.97
  • PyPI (open-source maintainers) — AI/MCP & workflow PyPI packages
    Vulnerable versions: pantheon-agents 0.6.1; pantheon-agents 0.6.2; pantheon-toolsets 0.5.5; pantheon-toolsets 0.5.6; magique 0.6.8; magique 0.6.9; magique-ai 0.4.4; magique-ai 0.4.5; executor-engine 0.3.4; executor-engine 0.3.5
  • PyPI (typosquats) — requests / Flask typosquat packages
    Vulnerable versions: rsquests; tlask; rlask
  • npm (open-source maintainers) — Related Miasma npm wave (same campaign)
    Vulnerable versions: 106 npm packages / 411 artifacts incl. Red Hat Hybrid Cloud Console ecosystem

Remediation for Shai-Hulud 'Hades' Campaign

Patches

  • No vendor patch — remove malicious package versions and install only known-good releases once republished by maintainers

Immediate actions

  • Inventory environments for the affected package names/versions (e.g., dynamo-release 1.5.4, spateo-release 1.1.2, coolbox 0.4.1-0.4.2, ufish, napari-ufish, ensmallen 0.8.101, embiggen 0.11.97, gpsea 0.9.14, pyphetools 0.9.120, pantheon-agents, magique-ai, langchain-core-mcp) and uninstall/quarantine them
  • Hunt for *-setup.pth files and _index.js in site-packages, and for the sentinel /tmp/.bun_ran
  • Search for unexpected Bun installs (bun-v1.3.13 / v1.3.14) and outbound requests to api.anthropic.com/v1/api
  • Rotate ALL credentials reachable from affected hosts/CI: GitHub/npm/PyPI/RubyGems/JFrog/CircleCI tokens, AWS/GCP/Azure/Kubernetes/Vault secrets, SSH keys
  • Audit GitHub orgs for newly created repos described 'Hades - The End for the Damned' and unexpected 'Run Copilot' workflows; delete and revoke associated tokens

Workarounds

  • Set PYTHONNOUSERSITE / use isolated environments and audit .pth files before running Python
  • Block outbound GitHub repo-creation from CI service accounts that should not publish

Longer-term hardening

  • Pin and hash-verify dependencies; require lockfiles with integrity hashes for pip/uv installs
  • Run installs and CI in ephemeral, network-egress-restricted sandboxes that block startup .pth side effects
  • Deploy CI hardening (e.g., egress allow-listing / Harden-Runner-style controls) and EDR with in-memory credential-access detection
  • Restrict and scope OIDC trusted publishing; require human approval for package publish steps

Weaknesses (CWE) in Shai-Hulud 'Hades' Campaign

CWE-506, CWE-829, CWE-494, CWE-1357, CWE-522

Timeline of Shai-Hulud 'Hades' Campaign

  • Original Shai-Hulud self-replicating supply-chain campaign begins across the npm ecosystem (attributed to TeamPCP).
  • Shai-Hulud 'Second Coming' wave hits npm: 500+ packages compromised across major maintainers, with the worm abusing GitHub Actions workflows and exfiltrating harvested credentials to attacker-created public GitHub repositories — the playbook later reused in the Hades PyPI wave.
  • TeamPCP releases worm source code; copycat/clone variants (Mini Shai-Hulud, Miasma) emerge shortly after.
  • Coordinated new-wave Shai-Hulud/Miasma attacks begin across npm and PyPI.
  • Miasma npm wave reported; JFrog documents compromise of Red Hat Hybrid Cloud Console JavaScript packages; 57+ npm packages / 300+ malicious versions tracked.
  • Hades PyPI wave first detected: 19 trojanized PyPI packages across 37 malicious wheels using *-setup.pth startup hooks that fetch Bun and run _index.js.
  • Six bioinformatics package versions published to PyPI in under 60 seconds; secondary wave adds 23 more PyPI artifacts targeting MCP/AI developers; Socket/SocRadar/StepSecurity/Endor publish analyses.
  • PyPI and GitHub begin removing the trojanized packages and disabling the 'Hades — The End for the Damned'-branded exfiltration repositories; vendors publish IOC lists and remediation guidance urging credential rotation (npm, GitHub, cloud, PyPI tokens) for any environment that installed an affected package.
  • The Hacker News and additional outlets report the campaign; tracker grows to 471 total artifacts (411 npm across 106 packages; 60 PyPI across 37 packages).

Sources cited for Shai-Hulud 'Hades' Campaign

Threats related to Shai-Hulud 'Hades' Campaign

Detection coverage for TL-2026-0734

As of 2026-06-09, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-0734 across Splunk SPL, Microsoft KQL and Sigma, covering 29 indicator(s) of compromise. The whole corpus is readable without an account; a free account unlocks full detection query text in Splunk SPL, Microsoft KQL and Sigma; paid tiers add raw indicator values, correlation and the MCP server. Threadlinqs MCP server · View plans.

Further reading

Threadlinqs Intelligence — Real-Time Threat Detection Platform

[ 0 threats ] [ 0 det ] [ CRIT: 0 ] [ HIGH: 0 ]
// threat_feed
$ sort --newest
Showing all threats

Latest Threats