Feed
CriticalPublished 19 May 2026Updated 29 May 20261 package · 3 versions

Microsoft `durabletask` PyPI compromised — TeamPCP Mini Shai-Hulud stage-2 dropper

Summary

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.

credential-theftwormci-cd-compromisemaintainer-takeoverobfuscation
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-command with AWS-RunShellScript against 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 exec into up to 5 running pods.
  • Encrypted HTTPS exfil defeats most outbound TLS inspection.
  • Dropper executes on import durabletaskpip install --no-deps does NOT mitigate; only pinning away from 1.4.1/1.4.2/1.4.3 does.

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)

  • PyPIdurabletask
    1.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 exec into 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 durabletaskpip install --no-deps does NOT mitigate; only pinning away from 1.4.1/1.4.2/1.4.3 does

What to do

  1. 1Pin durabletask to <= 1.4.0 everywhere. Refuse 1.4.1, 1.4.2, and 1.4.3 in lockfiles and constraints
  2. 2Purge any cached wheels of durabletask-1.4.{1,2,3} from CI image layers, pip caches, and internal mirrors
  3. 3Treat every host or runner that ran import durabletask with 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
  4. 4Audit CloudTrail / Azure Activity / GCP Audit for unexpected ssm:SendCommand, secretsmanager:GetSecretValue, kv:GetSecret, secretmanager.versions.access calls during the exposure window starting 2026-05-19T16:19Z
  5. 5Audit Kubernetes audit logs for unexpected pods/exec calls — the worm uses kubectl-exec into other pods to spread
  6. 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/version or /v1/models paths to non-allow-listed hosts
  7. 7Hunt for the rope.pyz file by SHA-256 069ac1dc7f7649b76bc72a11ac700f373804bfd81dab7e561157b703999f44ce on every Python host that ran the bad versions
  8. 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

pypi-2026-05-19-durabletask-teampcp