By falco365 · Published May 19, 2026

durabletask PyPI (TeamPCP/Mini Shai-Hulud): multi-cloud credential stealer with lateral movement and conditional wiper

Three trojanized versions of Microsoft's official durabletask Python SDK (1.4.1, 1.4.2, 1.4.3) were published to PyPI on May 19, 2026 using compromised publishing credentials. The payload (rope.pyz) is the most capable TeamPCP/Mini Shai-Hulud intrusion framework to date: multi-cloud credential theft across AWS, Azure, and GCP, Kubernetes secret enumeration, 99 developer tooling paths, password manager vault access, lateral movement via AWS SSM SendCommand and kubectl exec, Russian folklore-themed GitHub exfiltration repositories, and a conditional destructive wiper targeting specific geographies.

durabletask PyPI (TeamPCP/Mini Shai-Hulud): multi-cloud credential stealer with lateral movement and conditional wiper
Analysis

Three versions of Microsoft's official durabletask Python SDK — 1.4.1, 1.4.2, and 1.4.3 — were published to PyPI on May 19, 2026 using compromised publishing credentials, bypassing the repository's CI/CD pipeline entirely. The package (the Azure Durable Task Framework for Python) averages roughly 16,000 downloads per day. Microsoft confirmed the compromise and delisted the affected versions. The attack has been linked to the TeamPCP threat group and its Mini Shai-Hulud campaign — the same operation behind TanStack, Mistral AI, LiteLLM, and the @antv compromises.

The rope.pyz second-stage payload is the most capable TeamPCP intrusion framework documented to date. It goes beyond passive credential collection: it spreads laterally through AWS SSM SendCommand and Kubernetes kubectl exec, enumerates secrets from every cloud provider and namespace accessible from the compromised environment, and includes a conditional destructive wiper targeting specific geographies — the same conditional destructive component seen in the Mini Shai-Hulud TanStack/Mistral wave.

Publish chain: no Trusted Publishing, direct token upload

The attacker published directly to PyPI using compromised credentials. No corresponding version tags or CI/CD workflow runs exist in the GitHub repository — the commits that would normally precede a release are absent. The repository does not use PyPI Trusted Publishing (OIDC), so there was no mechanism to reject an upload from outside the CI/CD pipeline. This is the structural gap that made the attack possible: durabletask's publishing model relied on long-lived PyPI tokens rather than short-lived OIDC credentials tied to a specific workflow run.

The three versions were published in a 35-minute window on May 19, 2026:

VersionUpload time (UTC)Files infected
1.4.116:191 (__init__.py)
1.4.216:492 (__init__.py, task.py)
1.4.316:545 (__init__.py, task.py, entities/__init__.py, extensions/__init__.py, payload/__init__.py)

Each version expanded the infection surface, reaching more files in the package structure. The 5-minute gap between 1.4.2 and 1.4.3 suggests automated publishing rather than manual iteration.

rope.pyz: credential collection scope

Each trojanized version runs a dropper at import time on Linux hosts that fetches the second-stage payload (rope.pyz) from the C2 server. The collection scope is broader than any prior TeamPCP payload:

  • Cloud provider credentials: AWS access keys, EC2 instance metadata, Secrets Manager and SSM Parameter Store values across 19 regions. Azure service principals, Key Vault secrets, and managed identity tokens. GCP service account keys and Secret Manager entries.
  • Kubernetes: Kubeconfig files and service account tokens. Dumps secrets from every namespace and context — not just the default namespace.
  • Developer tooling: 99 hardcoded credential paths covering SSH keys, Git credentials, Docker configs, npm/PyPI/Cargo tokens, Terraform state, shell histories, .env files, and IDE/AI tool configurations.
  • Password managers: 1Password, Bitwarden, pass, and gopass vaults.
  • HashiCorp Vault: Tokens and AppRole credentials. Enumerates all KV mounts.
Lateral movement: AWS SSM and kubectl exec

The framework spreads beyond the initial compromised host through two mechanisms:

  • AWS SSM SendCommand: Using stolen AWS credentials with SSM permissions, the payload issues SendCommand to run collection and payload-fetch commands on other EC2 instances in the same account. This turns a single compromised developer machine or CI runner into access to the entire EC2 fleet reachable by the stolen IAM role.
  • Kubernetes kubectl exec: Using stolen kubeconfig credentials, the payload executes commands inside running containers across all accessible namespaces. Any Kubernetes workload reachable by the stolen service account token becomes a lateral movement target.

This is qualitatively different from the credential-collection-only behavior of earlier TeamPCP PyPI victims (litellm, xinference, lightning). The operator is not just stealing credentials — they are moving through infrastructure in real time.

Russian folklore exfiltration repositories

Harvested data is committed to public GitHub repositories created under victim accounts. The repository names follow a Russian folklore theme: BABA-YAGA, KOSCHEI, FIREBIRD, VASSILISA, RUSALKA. This is a new exfiltration branding distinct from the prior Mini Shai-Hulud Dune-themed repository names (sayyadina-stillsuit-852, etc.). Both patterns serve the same operational function — using the victim's own GitHub credentials to host encrypted stolen data — but the branding shift may indicate different sub-teams or an intentional diversification.

Persistence and artifacts
  • Dropper: /tmp/managed.pyz
  • Persistence: pgsql-monitor.service systemd unit — named to blend with legitimate PostgreSQL monitoring processes
  • Marker file: ~/.cache/.sys-update-check — singleton lock preventing re-execution
Indicators of compromise

Compromised versions:

  • durabletask==1.4.1 — malicious
  • durabletask==1.4.2 — malicious
  • durabletask==1.4.3 — malicious
  • durabletask==1.4.0 — last known clean release

File hashes (SHA-256):

  • durabletask-1.4.1 wheel: 7d80b3ef74ad7992b93c31966962612e4e2ceb93e7727cdbd1d2a9af47d44ba8
  • durabletask-1.4.1 sdist: 3de04fe2a76262743ed089efa7115f4508619838e77d60b9a1aab8b20d2cc8bf
  • durabletask-1.4.2 wheel: aeaf583e20347bf850e2fabdcd6f4982996ba023f8c2cd56bbd299cfd56516f5
  • rope.pyz payload: 069ac1dc7f7649b76bc72a11ac700f373804bfd81dab7e561157b703999f44ce

C2 infrastructure (defanged):

  • check.git-service[.]com — primary C2 domain (NameSilo, registered 2026-05-16, 3 days before attack)
  • t.m-kosche[.]com — secondary domain, known TeamPCP infrastructure (also used in @antv wave)
  • 160.119.64[.]3 — IP (AS7489, HostUS)

Host artifacts:

  • /tmp/managed.pyz — dropper
  • pgsql-monitor.service — systemd persistence unit
  • ~/.cache/.sys-update-check — marker file
  • Unexpected public GitHub repositories named BABA-YAGA, KOSCHEI, FIREBIRD, VASSILISA, or RUSALKA under victim accounts
Detection and remediation
  1. Pin to 1.4.0 immediately. Run pip show durabletask; if 1.4.1, 1.4.2, or 1.4.3, treat the system as breached.
  2. Treat any import as a full breach. The payload runs at import time on Linux. Any Python process that imported the malicious package executed the dropper.
  3. Rotate all cloud credentials from affected systems. AWS access keys, Azure service principal secrets, GCP service account keys, Kubernetes service account tokens, SSH keys, GitHub tokens, npm/PyPI tokens, HashiCorp Vault tokens, and password manager material.
  4. Check AWS CloudTrail for SendCommand API calls from compromised instances to identify lateral movement targets.
  5. Check Kubernetes audit logs for anomalous kubectl exec activity across namespaces during the May 19 window.
  6. Audit GitHub for Russian folklore-named repositories under any account whose tokens may have been exposed.
  7. Remove persistence: Delete pgsql-monitor.service and ~/.cache/.sys-update-check.
  8. Enable PyPI Trusted Publishing. This prevents direct token-based uploads from outside CI/CD.
Criminal-market signal

No dark-web presence for durabletask compromise tooling or rope.pyz infrastructure has been observed. The confirmed TeamPCP operator-run pattern documented across the cluster applies. The lateral-movement capability (SSM SendCommand, kubectl exec) is consistent with direct operator use of stolen credentials — a commodity actor would not need to move laterally when the credential collection payload has already harvested everything accessible. H2 (operator-run, no commodity market) is confirmed.