← Back to Cybersecurity News Center
Severity
CRITICAL
CVSS
9.5
Priority
0.938
×
Tip
Pick your view
Analyst for full detail, Executive for the short version.
Analyst
Executive
Executive Summary
Threat actor TeamPCP breached a GitHub employee device via a trojanized VS Code extension, exfiltrating approximately 3,800 internal Microsoft/GitHub repositories and forcing emergency rotation of critical secrets across Microsoft infrastructure. Simultaneously, TeamPCP deployed a self-replicating worm called Mini Shai-Hulud inside Microsoft-affiliated durabletask PyPI package versions 1.4.1 through 1.4.3, which has approximately 417,000 downloads per month and is used across Dapr and Azure-connected Python workloads. Organizations building on GitHub or running Python environments with these packages face cascading risk: stolen source code, harvested cloud credentials, and active lateral movement across AWS, Kubernetes, HashiCorp Vault, and secrets management platforms.
Impact Assessment
CISA KEV Status
Not listed
Threat Severity
CRITICAL
Critical severity — immediate action required
Actor Attribution
HIGH
TeamPCP
TTP Sophistication
HIGH
18 MITRE ATT&CK techniques identified
Detection Difficulty
HIGH
Multiple evasion techniques observed
Target Scope
INFO
GitHub internal repositories (Microsoft); durabletask PyPI package versions 1.4.1-1.4.3 (Microsoft/Dapr, ~417,000 downloads/month); Nx Console VS Code extension; guardrails-ai PyPI package; AWS EC2/SSM, Kubernetes, HashiCorp Vault, 1Password, Bitwarden, Docker, SSH environments
Are You Exposed?
⚠
Your industry is targeted by TeamPCP → Heightened risk
⚠
You use products/services from GitHub internal repositories (Microsoft); durabletask PyPI package versions 1.4.1-1.4.3 (Microsoft/Dapr → Assess exposure
⚠
18 attack techniques identified — review your detection coverage for these TTPs
✓
Your EDR/XDR detects the listed IOCs and TTPs → Reduced risk
✓
You have incident response procedures for this threat type → Prepared
Assessment estimated from severity rating and threat indicators
Business Context
A breach of GitHub's internal repositories exposes proprietary source code, internal tooling, and secrets that could be used to compromise downstream products, customer-facing services, or partner integrations at scale. The credential-stealing worm embedded in a widely used Python package creates a direct path to unauthorized access across cloud infrastructure, potentially enabling data theft, service disruption, or ransomware deployment in any organization running affected Python workloads. Organizations in regulated industries that rely on GitHub-hosted code or Dapr/Azure Python SDKs face compounding regulatory exposure, because stolen credentials and source code may constitute a reportable data breach under GDPR, SOC 2, or sector-specific frameworks.
You Are Affected If
You have durabletask Python package versions 1.4.1, 1.4.2, or 1.4.3 installed in any environment (production, staging, CI/CD, or developer workstation)
You use the guardrails-ai PyPI package in any Python environment
You have the Nx Console VS Code extension installed, especially if sourced outside the official VS Code Marketplace
Your CI/CD pipelines or application environments run on AWS EC2 or Kubernetes with cloud credentials accessible at runtime
Your developers or build systems have access to HashiCorp Vault tokens, 1Password, Bitwarden, or SSH key material on the same hosts where Python packages execute
Board Talking Points
A threat actor breached GitHub's internal systems and embedded credential-stealing malware in a widely used Python package, creating simultaneous exposure across source code repositories and cloud infrastructure.
Security teams should immediately audit all Python environments for the three affected package versions and rotate cloud credentials on any affected host, targeting completion within 24 hours.
Delayed action leaves cloud credentials, SSH keys, and secrets management vaults exposed to active exfiltration and potential lateral movement, which could escalate to a broader infrastructure compromise or ransomware event.
Technical Analysis
TeamPCP executed a dual-vector attack.
In the platform breach vector, a trojanized VS Code extension compromised a GitHub employee device (MITRE T1176 , T1554 ), enabling exfiltration of approximately 3,800 internal repositories and triggering emergency secret rotation across Microsoft infrastructure.
The Nx Console VS Code extension was also implicated.
In the supply chain vector, TeamPCP injected malicious code into durabletask PyPI package versions 1.4.1, 1.4.2, and 1.4.3 and the guardrails-ai PyPI package. The embedded Mini Shai-Hulud worm (T1195.001 ) harvests credentials from AWS EC2 instance metadata service (IMDS) (T1552.005 ), Kubernetes service account tokens, HashiCorp Vault tokens, 1Password, Bitwarden vault data, SSH key material (T1552.004 ), and major cloud provider credential stores (T1552 , T1552.001 ). Propagation logic targets AWS EC2 and Kubernetes environments (T1021 , T1021.001 , T1021.004 ) with exfiltration over HTTP/S (T1071.001 , T1567 , T1567.001 ). Persistence mechanisms (T1543 ) and valid account abuse (T1078 , T1078.004 ) facilitate lateral movement. Data destruction capability (T1485 ) is also indicated. Relevant CWEs: CWE-732 (incorrect permission assignment), CWE-522 (insufficiently protected credentials), CWE-312 (cleartext storage of sensitive information), CWE-494 (download of code without integrity check). No CVE has been assigned. Affected packages have been removed from PyPI; safe versions are 1.4.0 and below or 1.4.4 and above if released.
Action Checklist IR ENRICHED
Triage Priority:
IMMEDIATE
Escalate to CISO, legal counsel, and external IR retainer immediately if CloudTrail or Kubernetes audit logs confirm credential use outside the organization's AWS regions or Kubernetes clusters during the exposure window, if any of the ~3,800 exfiltrated GitHub repositories contain customer PII/PHI (triggering breach notification obligations under GDPR, CCPA, or HIPAA), or if the Mini Shai-Hulud worm is confirmed to have propagated beyond initially identified hosts to production systems.
1
Step 1: Containment — Audit all Python environments for durabletask 1.4.1–1.4.3 and guardrails-ai; isolate affected hosts from network access immediately. Suspend GitHub Actions and CI/CD pipelines pulling these packages. Revoke and rotate all cloud credentials accessible from affected hosts: AWS IAM roles, EC2 instance metadata credentials, Kubernetes service account tokens, HashiCorp Vault tokens, 1Password/Bitwarden vault credentials, and SSH keys. (Cite: NIST AC-2 / Account Management — revoke access from compromised identities; NIST AC-6 / Least Privilege — scope remaining credentials to minimum required access; D3-CRO / Credential Rotation — rotate all credentials accessible from affected hosts; D3-CH / Credential Hardening — harden remaining credential configurations post-rotation; CIS 6.2 / Establish an Access Revoking Process — follow documented process to disable compromised accounts and tokens)
IR Detail
Containment
NIST 800-61r3 §3.3 — Containment Strategy
NIST IR-4 (Incident Handling)
NIST AC-17 (Remote Access)
NIST SC-7 (Boundary Protection)
CIS 7.1 (Establish and Maintain a Vulnerability Management Process)
CIS 7.2 (Establish and Maintain a Remediation Process)
Compensating Control
Run `pip list --format=columns | grep -E 'durabletask|guardrails'` across all Python environments via SSH batch (pdsh or pssh) or Ansible ad-hoc command. For CI/CD, immediately set GitHub Actions environment protection rules to require manual approval, blocking any workflow referencing durabletask. Block outbound traffic from affected hosts using iptables: `iptables -I OUTPUT -m owner --uid-owner <service-user> -j DROP` until package audit completes. Use `aws iam list-attached-role-policies` and `aws iam delete-access-key` via AWS CLI to revoke compromised IAM keys. Rotate SSH keys by removing suspect public keys from ~/.ssh/authorized_keys on affected hosts and regenerating with `ssh-keygen -t ed25519`.
Preserve Evidence
Before isolating, capture full network connection state from affected hosts: `ss -tunap > /evidence/netstat_$(hostname)_$(date +%s).txt` to document active C2 or exfiltration sessions originating from the Mini Shai-Hulud worm's self-propagation mechanism. Capture running process tree: `ps auxf > /evidence/proctree_$(hostname)_$(date +%s).txt` to identify any child processes spawned by durabletask's malicious __init__.py or setup.py payload. Dump environment variables of the Python interpreter process: `cat /proc/<python-pid>/environ | tr '\0' '\n' > /evidence/env_$(hostname)_$(date +%s).txt` to capture any AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, VAULT_TOKEN, or KUBECONFIG values resident in memory. Preserve pip cache directory at ~/.cache/pip/wheels/ and site-packages/durabletask* before removal to retain the malicious package artifacts for forensic analysis.
2
Step 2: Detection — Query package manifests, requirements.txt, pyproject.toml, Pipfile.lock, and Poetry lock files across all environments for durabletask==1.4.1, 1.4.2, or 1.4.3 and flagged guardrails-ai versions. In AWS CloudTrail, query for IMDS calls to 169.254.169.254 from EC2 instances running Python workloads, unexpected AssumeRole and GetSessionToken events, and outbound data transfers to unknown endpoints. In Kubernetes audit logs, filter for service account token reads outside normal application behavior. Review VS Code extension inventories for Nx Console installed from unofficial sources. Check DNS and HTTP proxy logs for C2 beacon patterns from developer or CI/CD hosts. (Cite: NIST AU-2 / Event Logging — enable logging of authentication, credential access, and network events; NIST AU-6 / Audit Record Review, Analysis, and Reporting — review CloudTrail, Kubernetes, and proxy logs for anomalous indicators; NIST AU-12 / Audit Record Generation — ensure audit records are generated across EC2, Kubernetes, and CI/CD systems; CIS 8.2 / Collect Audit Logs — confirm audit logging is enabled across all affected enterprise assets; D3-LAM / Local Account Monitoring — monitor local and service accounts for unauthorized activity; D3-SFA / System File Analysis — inspect package manifest and lock files for tampered or malicious entries)
IR Detail
Detection & Analysis
NIST 800-61r3 §3.2 — Detection and Analysis
NIST SI-4 (System Monitoring)
NIST AU-6 (Audit Record Review, Analysis, and Reporting)
NIST AU-2 (Event Logging)
NIST IR-5 (Incident Monitoring)
CIS 8.2 (Collect Audit Logs)
CIS 7.1 (Establish and Maintain a Vulnerability Management Process)
Compensating Control
Run `find / -name 'requirements*.txt' -o -name 'pyproject.toml' -o -name 'Pipfile.lock' 2>/dev/null | xargs grep -l 'durabletask'` to locate all dependency files referencing the package. For AWS CloudTrail without a SIEM, use AWS CLI: `aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRole --start-time <incident-window-start>` and separately query for IMDS abuse using VPC Flow Logs filtered to destination 169.254.169.254. For Kubernetes, run `kubectl get events --all-namespaces --field-selector reason=TokenReview` and review API server audit log at /var/log/kubernetes/audit.log filtering on `verb=create` and `resource=serviceaccounts/token`. For VS Code extension detection, run `ls ~/.vscode/extensions/ | grep -i nx-console` on developer workstations and compare install path metadata against the official publisher ID `nrwl.angular-console`. Deploy the public Sigma rule for T1071.001 (Application Layer Protocol: Web Protocols) against proxy/DNS logs using `sigma convert` with grep backend as a no-SIEM fallback. Use osquery: `SELECT name, version, path FROM python_packages WHERE name IN ('durabletask', 'guardrails-ai')` to enumerate affected hosts at scale.
Preserve Evidence
AWS CloudTrail logs filtered for the exposure window: specifically `GetCallerIdentity`, `AssumeRole`, `GetSecretValue` (Secrets Manager), and `DescribeInstances` API calls originating from EC2 instance profile ARNs associated with durabletask-running workloads — the Mini Shai-Hulud worm targets IMDS at 169.254.169.254/latest/meta-data/iam/security-credentials/ to harvest temporary credentials. Kubernetes API server audit logs at /var/log/kubernetes/audit.log for `TokenRequest` and `create/serviceaccounts/token` events outside normal application namespaces, indicating the worm's lateral movement toward cluster credentials. DNS query logs from Route 53 Resolver or on-prem DNS showing repeated resolution of domains not in the application's normal baseline from Python runtime processes — the worm's C2 beacon pattern via T1071.001 (MITRE ATT&CK T1071.001). GitHub audit log (if accessible) for bulk repository clone or download events from the compromised employee account during the breach window, specifically `git.clone` or `repos.download` event types covering the ~3,800 exfiltrated repositories. VS Code extension directory on developer workstations at `%APPDATA%\Code\User\extensions\` (Windows) or `~/.vscode/extensions/` (Linux/macOS) for Nx Console extension folders with modified timestamps inconsistent with official Marketplace release dates, indicating trojanized installation.
3
Step 3: Eradication — Remove durabletask 1.4.1–1.4.3 and downgrade to 1.4.0 or upgrade to a verified clean release from the official Dapr repository. Remove all guardrails-ai versions flagged in vendor advisories. Uninstall Nx Console extensions sourced outside the official VS Code Marketplace and reinstall from the verified publisher. Re-image any host confirmed to have executed malicious package code. Rotate all credentials identified in Step 1 on every host in the exposure window, even where compromise is unconfirmed. Remove any unauthorized IAM users, roles, or Kubernetes cluster role bindings created during the exposure window. (Cite: NIST AC-2 / Account Management — remove unauthorized accounts and roles created by the attacker; NIST AC-6 / Least Privilege — verify all retained accounts operate at minimum necessary privilege post-eradication; CIS 2.3 / Address Unauthorized Software — remove unauthorized package versions from all enterprise assets; CIS 2.2 / Ensure Authorized Software is Currently Supported — replace removed packages with verified, supported versions; CIS 7.4 / Perform Automated Application Patch Management — apply verified clean package versions through automated patch management; D3-UAP / User Account Permissions — restrict account permissions after removing unauthorized role bindings; D3-CRO / Credential Rotation — complete rotation of all exposed credentials)
IR Detail
Eradication
NIST 800-61r3 §3.4 — Eradication
NIST SI-2 (Flaw Remediation)
NIST SI-3 (Malicious Code Protection)
NIST SI-7 (Software, Firmware, and Information Integrity)
NIST CM-3 (Configuration Change Control)
CIS 7.3 (Perform Automated Operating System Patch Management)
CIS 7.4 (Perform Automated Application Patch Management)
CIS 2.2 (Ensure Authorized Software is Currently Supported)
Compensating Control
Verify durabletask 1.4.0 package integrity before installation by comparing SHA-256 hash against the value published on PyPI: `pip download durabletask==1.4.0 --no-deps -d /tmp/pkg_verify && sha256sum /tmp/pkg_verify/durabletask*.whl`. For Nx Console, verify the reinstalled extension's VSIX hash matches the official Marketplace release by downloading directly: `code --install-extension nrwl.angular-console` and confirming the extension ID in `~/.vscode/extensions/nrwl.angular-console-*/package.json`. Write a YARA rule targeting Mini Shai-Hulud's known self-replication behavior (scanning for durabletask package directory traversal and IMDS HTTP request strings in Python bytecode) and run against site-packages: `yara -r /path/to/mini_shai_hulud.yar /usr/lib/python3/dist-packages/`. For confirmed-execution hosts, do not attempt in-place remediation — re-image from a known-good golden AMI or VM snapshot predating the durabletask 1.4.1 release date. Use `pip-audit` post-reinstall to confirm no remaining vulnerable packages: `pip-audit --require-hashes -r requirements.txt`.
Preserve Evidence
Before re-imaging, acquire a full memory dump of confirmed-execution hosts using LiME (Linux Memory Extractor) kernel module to preserve in-memory worm state, harvested credentials, and C2 communication buffers: `insmod lime.ko 'path=/evidence/mem_$(hostname).lime format=lime'`. Preserve the malicious durabletask package files intact at /usr/lib/python3/dist-packages/durabletask/ or the virtualenv equivalent — specifically __init__.py, setup.py, and any .pyc bytecode files that encode the worm's replication logic. Capture pip installation logs at ~/.local/share/pip/log/ or /var/log/pip.log to establish the exact timestamp durabletask 1.4.1–1.4.3 was installed, correlating with CloudTrail credential theft events. For developer workstations, export VS Code extension metadata: `cat ~/.vscode/extensions/*/package.json | python3 -c 'import sys,json; [print(d.get("publisher"),d.get("name"),d.get("version")) for d in [json.load(open(f)) for f in sys.argv[1:]]]'` to document the trojanized Nx Console version and installation source.
4
Step 4: Recovery — After credential rotation, verify new credentials are functional and access policies are scoped to least privilege per AC-6. Confirm no unauthorized IAM users, Kubernetes cluster role bindings, or Vault policies were created during the exposure window. Before restoring CI/CD pipelines, validate all pipelines pull from verified package sources with hash-pinned dependencies. Monitor AWS CloudTrail, Kubernetes audit logs, Vault audit logs, and developer endpoint logs for continued anomalous access patterns for a minimum of 30 days. (Cite: NIST AC-6 / Least Privilege — validate restored access follows least-privilege scoping; NIST AC-2 / Account Management — confirm all accounts active post-recovery are authorized and inventoried; NIST AU-6 / Audit Record Review, Analysis, and Reporting — conduct active log review for 30 days post-recovery to detect residual access; NIST AU-11 / Audit Record Retention — retain all audit records from the incident window consistent with retention policy; CIS 5.1 / Establish and Maintain an Inventory of Accounts — verify the account inventory reflects only authorized accounts post-recovery; CIS 8.2 / Collect Audit Logs — confirm logging remains active and complete across all restored systems; D3-LAM / Local Account Monitoring — continue monitoring for unauthorized local account activity during the recovery window)
IR Detail
Recovery
NIST 800-61r3 §3.5 — Recovery
NIST IR-4 (Incident Handling)
NIST AC-6 (Least Privilege)
NIST AC-2 (Account Management)
NIST AU-6 (Audit Record Review, Analysis, and Reporting)
NIST SI-7 (Software, Firmware, and Information Integrity)
CIS 5.1 (Establish and Maintain an Inventory of Accounts)
CIS 6.1 (Establish an Access Granting Process)
CIS 6.2 (Establish an Access Revoking Process)
Compensating Control
Enumerate all IAM users and roles created during the exposure window: `aws iam list-users --query 'Users[?CreateDate>=`<exposure-start>`]'` and `aws iam list-roles --query 'Roles[?CreateDate>=`<exposure-start>`]'`; cross-reference against your pre-incident IAM baseline. For Kubernetes, audit all ClusterRoleBindings and RoleBindings created during the window: `kubectl get clusterrolebindings,rolebindings --all-namespaces -o json | jq '.items[] | select(.metadata.creationTimestamp >= "<exposure-start>")'`. Set up a 30-day CloudTrail event history alert for the newly rotated IAM role ARNs using CloudWatch Metric Filter targeting `errorCode=AccessDenied` and `eventName=AssumeRole` to catch any attacker-held credential copies still attempting access. Validate CI/CD pipeline integrity by auditing GitHub Actions workflow YAML files for hardcoded package versions and replacing with hash-pinned references: `pip download <package> && pip hash <file>` to generate SHA-256 hashes for requirements.txt `--hash=sha256:` syntax.
Preserve Evidence
AWS CloudTrail `ListBuckets`, `GetObject`, and `PutObject` events from the exposure window to assess whether the worm or the TeamPCP actor exfiltrated data from S3 buckets accessible via the harvested EC2 instance profile credentials. HashiCorp Vault audit log (enabled via `vault audit enable file file_path=/var/log/vault_audit.log`) reviewed for secret reads on paths accessible to the compromised Vault tokens during the exposure window — specifically any `kv/data/` path reads that are anomalous relative to the application's normal access pattern. Kubernetes API server audit log entries for `create` verbs against `clusterrolebindings` or `secrets` resources within the exposure window, indicating privilege escalation attempts by the worm using harvested service account tokens. GitHub audit log export covering the breach window for `repo.download`, `git.clone`, and `org.invite` events tied to the compromised employee account to bound the scope of the ~3,800 repository exfiltration.
5
Step 5: Post-Incident — This campaign exposed three control gaps: absence of package integrity verification in CI/CD pipelines (T1195.001), insufficient secrets isolation on developer endpoints (T1552.001/T1552.004), and lack of VS Code extension allowlisting (T1176). Implement hash-pinned dependencies with automated integrity checks (pip-audit, Dependabot, or equivalent) for all PyPI packages. Enforce developer endpoint controls restricting cloud credential access to dedicated CI/CD service identities. Establish a VS Code extension allowlist enforced via MDM or workstation policy. Update the software inventory to include all IDE extensions as tracked enterprise assets. Review and formalize the access revoking process to enable rapid credential invalidation in future incidents. (Cite: NIST AC-6 / Least Privilege — restrict developer endpoint access to cloud credentials; NIST AC-20 / Use of External Systems — establish terms and conditions governing use of external package repositories and extension marketplaces; NIST AU-13 / Monitoring for Information Disclosure — monitor open-source repositories and PyPI for indicators of package compromise; CIS 2.1 / Establish and Maintain a Software Inventory — include VS Code extensions and PyPI packages in the software inventory; CIS 2.3 / Address Unauthorized Software — enforce removal of unauthorized or unallowlisted extensions and packages; CIS 6.2 / Establish an Access Revoking Process — formalize and automate credential revocation procedures; CIS 7.1 / Establish and Maintain a Vulnerability Management Process — incorporate third-party package and extension monitoring into the vulnerability management program; D3-CH / Credential Hardening — implement controls preventing developer workstations from directly holding production cloud credentials; D3-SFA / System File Analysis — continuously monitor package manifest and lock files for unauthorized modifications)
IR Detail
Post-Incident
NIST 800-61r3 §4 — Post-Incident Activity
NIST IR-4 (Incident Handling)
NIST IR-8 (Incident Response Plan)
NIST SI-2 (Flaw Remediation)
NIST SI-7 (Software, Firmware, and Information Integrity)
NIST SA-12 (Supply Chain Protection)
NIST CM-7 (Least Functionality)
CIS 7.1 (Establish and Maintain a Vulnerability Management Process)
CIS 7.2 (Establish and Maintain a Remediation Process)
CIS 2.1 (Establish and Maintain a Software Inventory)
CIS 2.3 (Address Unauthorized Software)
Compensating Control
For hash-pinned PyPI dependency enforcement without enterprise tooling, implement a pre-commit hook using `pip-audit` and `hashin`: install hashin (`pip install hashin`) and run `hashin durabletask==1.4.0 requirements.txt` to auto-populate SHA-256 hashes; enforce via `.pre-commit-config.yaml` with `pip-audit` as a hook. For VS Code extension allowlisting without MDM, deploy a startup script on developer workstations that compares installed extensions against an approved list: `code --list-extensions | grep -vFf /etc/vscode/approved_extensions.txt` and alerts or removes unapproved entries. For secrets isolation on developer endpoints, configure AWS credential profiles in ~/.aws/config to use `credential_process` pointing to a script that requires MFA or short-lived STS tokens, preventing long-lived credentials from residing on disk: `aws sts get-session-token --serial-number <mfa-arn> --token-code <otp>`. Implement a GitHub Actions workflow that runs `pip-audit --require-hashes` as a required status check before any build job executes, blocking pipelines that reference unverified package versions.
Preserve Evidence
Lessons-learned documentation should include a full timeline reconstructed from: pip installation logs, CloudTrail credential usage events, Kubernetes audit logs, GitHub audit logs, and DNS/proxy logs — correlated to establish when durabletask 1.4.1–1.4.3 first entered each environment, when the worm first made IMDS calls, and when TeamPCP first accessed exfiltrated GitHub repository data. Produce an inventory of all secrets confirmed or suspected to have been in scope during the exposure window, categorized by secret type (AWS IAM, Kubernetes SA token, Vault token, SSH key, password manager entry) and rotation status, to serve as evidence of breach scope for any required regulatory notification assessment. Retain the malicious durabletask package artifacts, memory dumps, and all log exports in write-protected, chain-of-custody storage for a minimum of 12 months per NIST AU-11 (Audit Record Retention) to support any future law enforcement referral or civil litigation related to TeamPCP's campaign.
Recovery Guidance
After credential rotation and pipeline restoration, maintain active monitoring of all newly issued AWS IAM role ARNs, Kubernetes service account tokens, and Vault token accessors for 30 days minimum, specifically alerting on any `AssumeRole` or `TokenReview` events from IP ranges not matching your known CI/CD or developer egress addresses — residual attacker-held credential copies from TeamPCP's exfiltration are a realistic persistence risk. Validate the integrity of all GitHub repositories accessible to the compromised employee account by comparing current repository contents against pre-incident commit hashes, checking for any unauthorized commits, branch protection rule changes, or webhook additions that may have been introduced during the breach window. Do not restore automated GitHub Actions workflows until all dependency files across all repositories have been audited for durabletask 1.4.1–1.4.3 references and updated to hash-pinned clean versions, as the worm's self-replication mechanism specifically targets CI/CD environments to propagate.
Key Forensic Artifacts
Python site-packages directory artifacts: malicious durabletask 1.4.1–1.4.3 __init__.py and setup.py files containing Mini Shai-Hulud worm payload code, preserved with original file timestamps and SHA-256 hashes, located at /usr/lib/python3/dist-packages/durabletask/ or within virtualenv lib/python*/site-packages/durabletask/ on affected hosts.
AWS CloudTrail logs for the exposure window filtered on EventNames: GetCredentials (IMDS), AssumeRole, GetSecretValue, ListBuckets, GetObject — specifically events where the sourceIPAddress field matches EC2 instance private IPs running durabletask workloads, evidencing the worm's automated credential harvesting from 169.254.169.254/latest/meta-data/iam/security-credentials/.
Linux process accounting logs (/var/log/psacct or auditd logs at /var/log/audit/audit.log) filtered for SYSCALL records with comm=python3 and EXECVE records showing child process execution (e.g., curl, wget, or base64) spawned by the durabletask package during its malicious initialization, consistent with worm staging and C2 callback behavior.
DNS resolver query logs from the exposure window for all queries originating from developer workstations or CI/CD runner hosts, specifically non-baseline fully qualified domain names resolved by Python interpreter processes — these represent the Mini Shai-Hulud worm's C2 beacon destinations via MITRE ATT&CK T1071.001 and are critical for IOC extraction and threat intelligence sharing.
GitHub audit log export (available via GitHub Enterprise audit log API or GitHub.com organization audit log) covering the breach window, specifically `git.clone`, `repo.download`, `repo.create_fork`, and `org.add_member` event types tied to the compromised employee account, bounding the scope of TeamPCP's ~3,800 repository exfiltration and identifying any secondary access or persistence mechanisms established within the GitHub organization.
Detection Guidance
Detection for this campaign spans four log domains.
Each is grounded in KB-verified controls.
1.
Package presence (T1195.001 — Supply Chain Compromise): Scan all environments for durabletask 1.4.1, 1.4.2, and 1.4.3 and flagged guardrails-ai versions using 'pip list', SBOM tooling, or pip-audit.
Search requirements.txt, Pipfile.lock, pyproject.toml, and Poetry lock files across developer endpoints and CI/CD runners. Ground: CIS 2.1 (software inventory must include third-party packages); NIST AU-12 (audit record generation must cover software installation events); D3-SFA (System File Analysis — monitor package manifest and lock files for tampered entries).
2. AWS IMDS credential access (T1552.005 — Cloud Instance Metadata API): In CloudTrail, query for HTTP requests to 169.254.169.254 originating from EC2 instances running Python workloads, especially outside normal application call patterns. Alert on unexpected AssumeRole, GetSessionToken, or ListBuckets calls following IMDS access within the same session. Ground: NIST AU-2 (event logging must include authentication and privileged-function events); NIST AU-6 (audit records must be reviewed for anomalous indicators); NIST AU-3 (audit records must capture what occurred, when, where, source, and outcome); D3-LAM (Local Account Monitoring — detect unauthorized use of instance-bound service identities).
3. Kubernetes service account token reads (T1552.001 , T1078.004 ): In Kubernetes audit logs, filter for GET requests to /var/run/secrets/kubernetes.io/serviceaccount/token or API server calls using service account tokens from unexpected source IPs or process contexts. Alert on token use outside normal application namespaces. Ground: NIST AU-6 (review audit records for indications of inappropriate activity); CIS 8.2 (audit logging must be enabled and collected across Kubernetes control planes); D3-LAM (monitor service accounts for activity deviating from established baseline).
4. Exfiltration over C2 channels (T1567 , T1071.001 ): Review HTTP/S proxy and DNS logs for outbound connections from developer workstations or CI/CD hosts to domains not in your known-good allowlist. Alert on connections initiated shortly after package installation or build execution. Look for DNS queries resolving to infrastructure with no prior organizational history. Ground: NIST AU-2 (log outbound network activity from build and developer systems); NIST AU-6 (analyze proxy and DNS logs for exfiltration indicators); NIST AC-4 (Information Flow Enforcement — enforce approved authorizations for outbound information flows); D3-PBWSAM (Proxy-based Web Server Access Mediation — route all outbound developer and CI/CD traffic through proxy for inspection and allowlisting).
5. Malicious VS Code extension activity (T1176 , T1554 ): Audit VS Code extension inventories on all developer endpoints for Nx Console versions installed from sources other than the official VS Code Marketplace. Cross-reference installed extension publisher IDs and version hashes against the official marketplace. Alert on any extension that does not match an allowlisted publisher and version. Ground: CIS 2.1 (software inventory must include IDE extensions as enterprise assets); CIS 2.3 (unauthorized software must be identified and removed); NIST AU-12 (generate audit records for software installation events on developer endpoints); D3-SFA (System File Analysis — inspect extension files and startup configurations for modifications consistent with T1554 Compromise Software Supply Chain).
6. Credential and account anomaly detection (T1078 , T1078.004 ): Monitor for new IAM users, roles, or Kubernetes cluster role bindings created during the exposure window that do not correspond to authorized provisioning requests. Alert on any account or role granted permissions exceeding what is documented in the access inventory. Ground: NIST AC-2 (Account Management — detect accounts created outside the provisioning process); CIS 5.1 (inventory of accounts must be maintained and auditable); D3-LAM (Local Account Monitoring — detect new or modified accounts on affected systems); D3-UAP (User Account Permissions — flag permission grants inconsistent with least-privilege policy).
Indicators of Compromise (3)
Export as
Splunk SPL
KQL
Elastic
Copy All (3)
1 hash
1 url
1 domain
Type Value Enrichment Context Conf.
# HASH
durabletask==1.4.1 / 1.4.2 / 1.4.3 (PyPI)
VT
MB
Malicious package versions containing Mini Shai-Hulud worm payload; exact file hashes not publicly confirmed at time of report — use version string for detection
HIGH
🔗 URL
https://pypi.org/project/durabletask/
VT
US
Official PyPI listing; versions 1.4.1–1.4.3 reported removed; verify current safe version before installing
HIGH
⌘ DOMAIN
169.254.169.254
VT
US
AWS EC2 IMDS endpoint targeted by worm for credential harvesting (T1552.005); unexpected calls from Python processes are a behavioral IOC
HIGH
Platform Playbooks
Microsoft Sentinel / Defender
CrowdStrike Falcon
AWS Security
🔒
Microsoft 365 E3
3 log sources
Basic identity + audit. No endpoint advanced hunting. Defender for Endpoint requires separate P1/P2 license.
🛡
Microsoft 365 E5
18 log sources
Full Defender suite: Endpoint P2, Identity, Office 365 P2, Cloud App Security. Advanced hunting across all workloads.
🔍
E5 + Sentinel
27 log sources
All E5 tables + SIEM data (CEF, Syslog, Windows Security Events, Threat Intelligence). Analytics rules, playbooks, workbooks.
Hard indicator (direct match)
Contextual (behavioral query)
Shared platform (review required)
IOC Detection Queries (2)
1 domain indicator(s). Detects DNS lookups and connections.
KQL Query Preview
Read-only — detection query only
// Threat: TeamPCP Breaches GitHub via Malicious VS Code Extension; Mini Shai-Hulud Worm Co
let malicious_domains = dynamic(["169.254.169.254"]);
DeviceNetworkEvents
| where Timestamp > ago(30d)
| where RemoteUrl has_any (malicious_domains)
| project Timestamp, DeviceName, RemoteUrl, RemoteIP, RemotePort,
InitiatingProcessFileName, InitiatingProcessCommandLine
| sort by Timestamp desc
Malicious URLs hosted on legitimate platforms. The domain is safe — the specific URL path is the indicator.
KQL Query Preview
Read-only — detection query only
// Threat: TeamPCP Breaches GitHub via Malicious VS Code Extension; Mini Shai-Hulud Worm Co
// Specific malicious URLs on shared platforms
let suspicious_urls = dynamic(["https://pypi.org/project/durabletask/"]);
DeviceNetworkEvents
| where Timestamp > ago(30d)
| where RemoteUrl has_any (suspicious_urls)
| project Timestamp, DeviceName, RemoteUrl, RemoteIP,
InitiatingProcessFileName, InitiatingProcessCommandLine
| sort by Timestamp desc
MITRE ATT&CK Hunting Queries (4)
Sentinel rule: Sign-ins from unusual locations
KQL Query Preview
Read-only — detection query only
SigninLogs
| where TimeGenerated > ago(7d)
| where ResultType == 0
| summarize Locations = make_set(Location), LoginCount = count(), DistinctIPs = dcount(IPAddress) by UserPrincipalName
| where array_length(Locations) > 3 or DistinctIPs > 5
| sort by DistinctIPs desc
Sentinel rule: Lateral movement via RDP / SMB / WinRM
KQL Query Preview
Read-only — detection query only
DeviceNetworkEvents
| where Timestamp > ago(7d)
| where RemotePort in (3389, 5985, 5986, 445, 135)
| where LocalIP != RemoteIP
| summarize ConnectionCount = count(), TargetDevices = dcount(RemoteIP) by DeviceName, InitiatingProcessFileName
| where ConnectionCount > 10 or TargetDevices > 3
| sort by TargetDevices desc
Sentinel rule: Unusual C2 communication patterns
KQL Query Preview
Read-only — detection query only
DeviceNetworkEvents
| where Timestamp > ago(7d)
| where RemotePort in (80, 443, 8080, 8443)
| where InitiatingProcessFileName !in~ ("chrome.exe", "msedge.exe", "firefox.exe", "teams.exe", "outlook.exe", "svchost.exe")
| summarize Connections = count() by DeviceName, RemoteIP, InitiatingProcessFileName
| where Connections > 50
| sort by Connections desc
Sentinel rule: Suspicious PowerShell command line
KQL Query Preview
Read-only — detection query only
DeviceProcessEvents
| where Timestamp > ago(7d)
| where FileName in~ ("powershell.exe", "pwsh.exe", "cmd.exe", "wscript.exe", "cscript.exe", "mshta.exe")
| where ProcessCommandLine has_any ("-enc", "-nop", "bypass", "hidden", "downloadstring", "invoke-expression", "iex", "frombase64", "new-object net.webclient")
| project Timestamp, DeviceName, FileName, ProcessCommandLine, AccountName, InitiatingProcessFileName
| sort by Timestamp desc
Falcon API IOC Import Payload (1 indicators)
POST to /indicators/entities/iocs/v1 — Weak/benign indicators pre-filtered. Expiration set to 90 days.
Copy JSON
[
{
"type": "domain",
"value": "169.254.169.254",
"source": "SCC Threat Intel",
"description": "AWS EC2 IMDS endpoint targeted by worm for credential harvesting (T1552.005); unexpected calls from Python processes are a behavioral IOC",
"severity": "high",
"action": "detect",
"platforms": [
"windows",
"mac",
"linux"
],
"applied_globally": true,
"expiration": "2026-08-19T00:00:00Z"
}
]
Route 53 DNS — Malicious Domain Resolution
Query Preview
Read-only — detection query only
fields @timestamp, qname, srcaddr, rcode
| filter qname in ["169.254.169.254"]
| sort @timestamp desc
| limit 200
Compliance Framework Mappings
T1078.004
T1021.001
T1552.001
T1554
T1567
T1071.001
+12
AC-2
AC-6
IA-2
IA-5
AC-17
AC-3
+4
A01:2021
A04:2021
A07:2021
A08:2021
164.308(a)(5)(ii)(D)
164.312(d)
MITRE ATT&CK Mapping
T1021.001
Remote Desktop Protocol
lateral-movement
T1552.001
Credentials In Files
credential-access
T1554
Compromise Host Software Binary
persistence
T1567
Exfiltration Over Web Service
exfiltration
T1552
Unsecured Credentials
credential-access
T1567.001
Exfiltration to Code Repository
exfiltration
T1078
Valid Accounts
defense-evasion
T1485
Data Destruction
impact
T1552.005
Cloud Instance Metadata API
credential-access
T1543
Create or Modify System Process
persistence
T1021
Remote Services
lateral-movement
T1195.001
Compromise Software Dependencies and Development Tools
initial-access
T1176
Software Extensions
persistence
Guidance Disclaimer
The analysis, framework mappings, and incident response recommendations in this intelligence
item are derived from established industry standards including NIST SP 800-61, NIST SP 800-53,
CIS Controls v8, MITRE ATT&CK, and other recognized frameworks. This content is provided
as supplemental intelligence guidance only and does not constitute professional incident response
services. Organizations should adapt all recommendations to their specific environment, risk
tolerance, and regulatory requirements. This material is not a substitute for your organization's
official incident response plan, legal counsel, or qualified security practitioners.
View All Intelligence →