Shai-Hulud 'Hades' Campaign — Trojanized PyPI Packages Auto-Execute Bun Credential Stealer via Python Wheel Startup Hooks (*-setup.pth) — Threadlinqs Intelligence
As of 2026-06-09, Shai-Hulud 'Hades' Campaign — Trojanized PyPI Packages Auto-Execute Bun Credential Stealer via Python Wheel Startup Hooks (*-setup.pth) is a critical-severity supply chain threat attributed to TeamPCP, tracked by Threadlinqs Intelligence with 9 detection rules (Splunk SPL, Microsoft KQL, Sigma) and 29 indicators of compromise.
Threat ID: TL-2026-0734 · Severity: CRITICAL · Status: ACTIVE · Category: SUPPLY_CHAIN
Attribution: TeamPCP · FINANCIAL
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
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
Weaknesses (CWE)
CWE-506, CWE-829, CWE-494, CWE-1357, CWE-522
Target sectors: technology, software-development, bioinformatics, scientific-research, healthcare, academia, open-source, ai-ml
Target regions: North America, Europe, Global
Detections & IOCs
As of 2026-07-28, this threat has 9 detection rule(s) across Splunk SPL, Microsoft KQL and Sigma, and 29 indicator(s) of compromise. Detection query text and full IOC values are available to authenticated users and programmatically via the Threadlinqs MCP server (Purple tier). View plans.
SUPPLY_CHAIN, CRITICAL, threat intelligence, cybersecurity, T1583, T1586, T1608, T1195, T1059, T1059, T1059, T1059, T1204, T1547