Microsoft `durabletask` PyPI compromised — TeamPCP Mini Shai-Hulud stage-2 dropper
Three malicious versions of durabletask — Microsoft's Python SDK for Azure Durable Functions (~417K monthly downloads) — were uploaded directly to PyPI inside a 35-minute window on 2026-05-19. None correspond to any git tag or CI run; the attacker bypassed Microsoft's pipeline with a stolen PyPI API token. Stage-2 is the full Mini Shai-Hulud credential-stealer with dedicated cloud-secret collectors. Attributed to TeamPCP. Last clean release: 1.4.0.
- Threat actor
- TeamPCP
- Detected by
- Wiz · StepSecurity · Endor Labs · Aikido · SafeDep
- Also known as
- Mini Shai-Hulud
- Ecosystems
- PyPI
- Packages tracked
- 1
What happened
On 2026-05-19, hours after the @antv npm burst, TeamPCP pushed three malicious versions of Microsoft's official durabletask Python SDK (~417K monthly downloads) directly to PyPI inside a 35-minute window: 1.4.1 at 16:19 UTC, 1.4.2 at 16:49 UTC, 1.4.3 at 16:54 UTC. None of the three have corresponding tags, releases, or CI runs in microsoft/durabletask-python. The attacker bypassed Microsoft's build pipeline entirely and uploaded with a stolen or compromised PyPI API token — almost certainly one of the long-lived tokens cycled out of the broader Mini Shai-Hulud credential cache.
Execution does not require an install hook. The malicious wheels carry a Python dropper injected into the package's source files that fires on import durabletask. The dropper silently fetches a 28,703-byte zipapp rope.pyz (SHA-256 069ac1dc7f7649b76bc72a11ac700f373804bfd81dab7e561157b703999f44ce) from a three-day-old C2 domain check.git-service[.]com (registered 2026-05-16 via Namecheap), with t.m-kosche[.]com/rope.pyz as a documented fallback.
Stage-2 is the full Mini Shai-Hulud credential-harvesting framework with dedicated collectors for AWS Secrets Manager + SSM Parameter Store, Azure Key Vault, GCP Secret Manager, Kubernetes secrets, HashiCorp Vault, password managers, and 90+ developer-tool configurations. Results are encrypted with an attacker RSA public key and POSTed to /api/public/version; /v1/models is the secondary retrieval endpoint. The payload skips hosts with a Russian locale.
- In-cloud worm propagation: when stage-2 detects an AWS IAM profile, it runs
aws ssm send-commandwithAWS-RunShellScriptagainst up to 5 enumerated EC2 instances per profile, dropping itself on each. - In-cluster worm propagation: when a Kubernetes service-account token is reachable, it uses
kubectl execinto up to 5 running pods. - Encrypted HTTPS exfil defeats most outbound TLS inspection.
- Dropper executes on
import durabletask—pip install --no-depsdoes NOT mitigate; only pinning away from1.4.1/1.4.2/1.4.3does.
Disclosed publicly within hours by Wiz, StepSecurity, Endor Labs, Aikido, SafeDep, and The Hacker News. C2 fingerprints (t.m-kosche.com) are shared with the same-day @antv burst and the actions-cool tag hijack later the same day, plus the earlier TanStack, Mistral AI, @uipath, LiteLLM, and Telnyx compromises — TeamPCP's consistent infrastructure tells. Microsoft has yanked all three versions on PyPI; the last clean release is durabletask 1.4.0 (2026-04-08).
Affected packages (1)
- PyPI
durabletask1.4.11.4.21.4.3
Impact
- Cloud credential and secret theft: AWS Secrets Manager + SSM Parameter Store, Azure Key Vault, GCP Secret Manager, Kubernetes secrets, HashiCorp Vault
- Developer-tool credentials harvested from 90+ config locations: env files, GitHub CLI, npm/pip/poetry tokens, SSH private keys, Terraform state, DB passwords, password managers
- In-cloud worm propagation: AWS SSM SendCommand with AWS-RunShellScript launches the stage-2 on up to 5 other EC2 instances per accessible IAM profile
- In-cluster worm propagation:
kubectl execinto up to 5 running pods when stage-2 detects a service-account token - Encrypted exfiltration to attacker-controlled C2 over HTTPS, defeating most outbound TLS inspection
- Dropper executes on
import durabletask—pip install --no-depsdoes NOT mitigate; only pinning away from 1.4.1/1.4.2/1.4.3 does
What to do
- 1Pin
durabletaskto<= 1.4.0everywhere. Refuse 1.4.1, 1.4.2, and 1.4.3 in lockfiles and constraints - 2Purge any cached wheels of
durabletask-1.4.{1,2,3}from CI image layers, pip caches, and internal mirrors - 3Treat every host or runner that ran
import durabletaskwith 1.4.1/1.4.2/1.4.3 installed as fully compromised. Rotate: AWS/Azure/GCP keys, every Secrets-Manager / Key-Vault / Secret-Manager entry reachable from that IAM scope, K8s service-account tokens, Vault tokens, npm/PyPI/GitHub/GitLab/CircleCI tokens, SSH keys, DB passwords, password-manager vaults - 4Audit CloudTrail / Azure Activity / GCP Audit for unexpected
ssm:SendCommand,secretsmanager:GetSecretValue,kv:GetSecret,secretmanager.versions.accesscalls during the exposure window starting 2026-05-19T16:19Z - 5Audit Kubernetes audit logs for unexpected
pods/execcalls — the worm uses kubectl-exec into other pods to spread - 6Block egress to
check.git-service.com,t.m-kosche.com, and any *.git-service.com subdomain; alert on outbound HTTP POST containing/api/public/versionor/v1/modelspaths to non-allow-listed hosts - 7Hunt for the rope.pyz file by SHA-256 069ac1dc7f7649b76bc72a11ac700f373804bfd81dab7e561157b703999f44ce on every Python host that ran the bad versions
- 8PyPI publishing for production projects: enforce Trusted Publishers (OIDC) and disable long-lived API tokens; the attacker only succeeded because a long-lived token was reachable
References
- StepSecurityMicrosoft's durabletask PyPI package compromised in supply-chain attackstepsecurity.io
- Wizdurabletask: TeamPCP's latest PyPI compromisewiz.io
- Endor LabsTrojanized Microsoft SDK: durabletask 1.4.1 through 1.4.3 deliver credential-stealing malwareendorlabs.com
- MicrosoftPotential malicious code execution in durabletask versions 1.4.1, 1.4.2, and 1.4.3 (microsoft/durabletask-python#137)github.com
- PyPIdurabletask on PyPI — versions 1.4.1 / 1.4.2 / 1.4.3 yanked as "Compromised"pypi.org