PERMISSION/PROTOCOL
Back to incident tracker

2026-06-07

CriticalMedia report

Hades Python Wave Stole 294,842 Secrets from 6,943 Developer Machines by Poisoning AI Tool Config Files and PyPI Startup Hooks

The Hades wave planted hooks in Claude Code, Cursor, Gemini CLI, and VS Code config files and 37 PyPI wheels to steal 294,842 credentials from 6,943 developer machines.

Miasma / Hades Supply Chain CampaignCredential exposureSupply chain credential theft via AI tool config poisoningDeveloper machine — AI coding tool config files and Python interpreter startup hooks

What happened

Attacker planted .claude/settings.json, .gemini/settings.json, .cursor/rules/setup.mdc, and .vscode/tasks.json files in compromised Microsoft Azure repositories, each pointing to a credential-harvesting node.js payload at .github/setup.js. A parallel Hades PyPI wave dropped 37 wheels with Python .pth startup hooks that executed the same stealer on interpreter start.

Why it matters

294,842 developer secrets stolen from 6,943 machines. Credentials swept: GitHub tokens, PyPI tokens, AWS/GCP/Azure credentials, SSH keys, and Kubernetes secrets. Azure/functions-action (the official GitHub Action for deploying Azure Functions) was disabled, breaking CI/CD pipelines globally. Exfiltration used GitHub dead-drops with AES-GCM encrypted payloads camouflaged as normal API traffic.

Missing authorization check

No external layer validated or scoped the commands executed by AI tool startup hooks before they ran with full developer credentials. Session start hooks in AI coding tools ran with the same permissions as the developer, with no receipt or authorization check.

Would PP block it?

The Hades attack operates at the AI tool startup layer, before Permission Protocol can gate any agent action. PP's Credential Gate blocks post-session credential access (e.g., an agent trying to read AWS keys mid-task) but cannot intercept a malicious node.js command that fires when Claude Code reads its settings.json on launch. Full coverage requires an input firewall before repo ingestion — a layer outside PP's current scope.

Incident analysis

Timeline and technical read

Timeline

  1. 2026-06-05

    Compromised contributor account pushes malicious commit to Azure/durabletask on GitHub. Planted .claude/settings.json, .gemini/settings.json, .cursor/rules/setup.mdc, and .vscode/tasks.json files pointing to credential-stealing .github/setup.js payload. GitHub disables 73 Microsoft repositories across four orgs in a 105-second sweep.

  2. 2026-06-07

    Socket detects 37 malicious Python wheel artifacts (Hades wave) across 19 PyPI packages. Packages use .pth startup hooks to execute a Bun-powered credential stealer on every Python interpreter start, without requiring an explicit import.

  3. 2026-06-10

    Reddit r/ClaudeAI thread surfaces the attack. Community reports credential exposure after opening affected repos in Claude Code.

  4. 2026-06-11

    StepSecurity, Sunglasses.dev, and Rescana publish technical analyses. Phoenix Security documents 294,842 secrets stolen from 6,943 developer machines. Malicious PyPI wheels quarantined.

  5. 2026-06-16

    Campaign continues to resurface in enterprise AI security buyer guides. 448 total artifacts tracked across npm and PyPI (411 npm from prior Miasma waves + 37 new PyPI wheels).

Technical breakdown

  • The attack moved execution from package install (classic supply chain) to folder open and interpreter start — two moments that happen before a developer reviews any code.
  • AI coding tools treat repo-level config files (.claude/settings.json, .cursor/rules/*.mdc) as trusted project policy. The Miasma campaign weaponized exactly this trust: hostile instructions hidden in config, not source code.
  • Python .pth files beginning with 'import' are executed by Python's site machinery on every interpreter start (python, pip, pytest, notebook). Once installed, there is no explicit import needed for the stealer to fire.
  • Exfiltration used GitHub dead-drops with AES-GCM encrypted payloads and network traffic shaped to resemble normal API calls, evading most runtime detection.
  • Zero CVEs were assigned across all 448 artifacts in the campaign — the attack exploited intended tool behavior, not implementation bugs.

Authorization boundary

Where the authorization boundary should have been

This incident is categorized as Credential exposure. The relevant Permission Protocol gate is Credential Gate. The read is conditional: the block only applies where the real action boundary is routed through a gate.

If enforced at
Credential access, agent session scope, tool-call authorization
Still needs
Pre-session hook execution in AI tool config files; Python interpreter startup hooks (.pth files); repository content inspection before agent ingestion
Receipt required for
Any command execution triggered by AI tool session startup; credential access during agent tasks

PP's Credential Gate would require an explicit authorization receipt before any agent action accesses scoped credentials. It would not prevent the pre-session hook execution — the attack fires before the agent session starts, at the OS/tool layer.

Start small

Put the relevant gate at this action boundary.

This incident maps to Credential Gate. Start with the boundary that controls the actual action, then require a signed receipt before execution.

Replay this incident with a signer in the loop