Sha1-Hulud / Shai-Hulud: Full Technical Dissection of TeamPCP’s. Self-Propagating Supply Chain Worm

Executive Summary

Sha1-Hulud is not a vulnerability in the conventional sense. There is no CVE, no memory safety bug, no mismatched HTTP parser. The Shai-Hulud-Open-Source reference implementation is, in its entirety, a multi-stage credential infostealer and supply chain attack platform. The whole codebase is the exploit.

Between late 2025 and mid-2026, the operators behind it — tracked publicly as TeamPCP, also identified as PCPcat, DeadCatx3, ShellForce, and CipherForce — industrialised this model across npm, PyPI, GitHub Actions, Docker Hub, OpenVSX, and IDE integrations. Every wave refined the tradecraft: new loaders, new persistence mechanisms, new exfiltration channels, and a growing target list that now includes AI SDK libraries, password manager CLIs, and the security scanners DevSecOps teams rely on to detect compromise.

Five things to carry out of this article: this is install-time code execution, not a CVE. The primary objective is credential theft and package republishing. The malware’s polymorphism is operational — loaders, filenames, hooks, and exfil paths rotate while the kill chain stays stable across every wave. Persistence now spans GitHub Actions, self-hosted runners, IDE and AI assistant configurations, Python import hooks, and package caches. And OIDC plus signed provenance do not protect you if the workflow identity is compromised — Mini Shai-Hulud generated cryptographically valid Sigstore provenance for backdoored releases. Standard SCA tooling was blind to every wave.

Key Findings from Phoenix Purple https://phoenix.security/phoenix-purple-ai-sast-sca-ai-generated-code/ 

TL;DR for Engineering Teams

What it isA self-propagating supply chain worm that steals credentials, backdoors npm/PyPI packages, establishes IDE and CI persistence, and abuses GitHub OIDC to republish malicious releases with valid Sigstore provenance. No CVE exists for any wave.
Where it bitesnpm preinstall/postinstall hooks; PyPI .pth import hooks; GitHub Actions pull_request_target workflows with id-token: write; .claude/ and .vscode/ IDE config directories; Python site-packages; systemd user services; Windows Startup folder.
Primary objectiveCredential harvest: GitHub tokens, npm tokens, AWS/GCP/Azure keys, Kubernetes tokens, Vault secrets, SSH keys, crypto wallets, AI assistant configs. Then automated package republishing using the stolen credentials.
Why CVE scanners miss itEntire campaign is CVE-invisible. Malicious versions pass signature checks. Mini Shai-Hulud wave produces Sigstore-verified provenance for backdoored packages. Tarball-vs-source divergence is the only reliable SCA signal.
Immediate actionSet ignore-scripts=true in CI. Audit pull_request_target workflows for id-token: write + untrusted checkout. Pin GitHub Actions to full commit SHA. Rotate all tokens exposed in CI during affected windows. Audit .pth, .claude/, and .vscode/ directories.

Malware Overview

FieldValue
Malware FamilyShai-Hulud V1/V2, Sha1-Hulud V3, CanisterWorm, Mini Shai-Hulud
Threat ActorTeamPCP (PCPcat, DeadCatx3, ShellForce, CipherForce, Persy_PCP)
Primary Ecosystemsnpm, PyPI, GitHub Actions, Docker Hub, OpenVSX
Malware TypeSelf-propagating supply chain worm — credential stealer — persistent implant
CVEsNone — across every known wave
Active ExploitationConfirmed — multiple campaigns 2025–2026
Credential TargetsGitHub tokens, npm tokens, AWS/GCP/Azure keys, K8s tokens, Vault secrets, SSH keys, crypto wallets, AI assistant configs
Scale (V2 wave)~700 malicious package versions; 25,000+ attacker-created/abused GitHub repos; 37 affected organisations
Scale (Mini Shai-Hulud)170 packages across 19 namespaces; 84 malicious TanStack versions in ~24 hours; >1.3M weekly-download packages affected
Destructive CapabilityConfirmed: rm -rf ~/ wiper gated on victim org membership

Kill Chain analysis with Phoenix Purple https://phoenix.security/phoenix-purple-ai-sast-sca-ai-generated-code/ 

Get early access to Phoenix Purple to find TRUE critical attack chain with exploits

Verified Kill Chain (src/index.ts)

Shai-Hulud-Open-Source is a fully operational attack platform. Every step below is verified against the published source code. The entire codebase is the exploit.

StepActionCode LocationVerified
1Python loader bootstraps Bun runtimesrc/assets/PYTHON_LOADER.py:48-98
2preflight() — check Russian locale, daemonize, acquire locksrc/index.ts:67-89
3checkTargetRepo() — if in opensearch-js CI, run NPM supply-chain backdoorsrc/index.ts:42-65
4setupQuickResults() — filesystem + shell + runner harvestsrc/index.ts:29-40
5Connect to primary C2 at git-tanstack.comsrc/index.ts:95-99
6Fallback: create GitHub repo, exfil via commitssrc/sender/github/createRepo.ts:58-105
7Run AWS SSM, Secrets Manager, K8s, Vault providerssrc/index.ts:136-142
8For each captured ghtoken: inject malicious workflow into victim repossrc/providers/actions/workflow.ts:193-233
9Encrypt all results with operator RSA pubkey, POST to C2src/sender/base.ts:40-70
10Cleanup: delete injected branches and workflow runssrc/providers/actions/workflow.ts:171-187

Encryption pipeline: data → JSON → gzip → AES-256-GCM(random key) → RSA-OAEP(operator pubkey) → base64. All sensitive strings in the binary are obfuscated via a custom scramble() function with AES-256-GCM encrypted constants in src/generated/index.ts. None are recoverable from the binary without the operator’s key.

Background: From Shai-Hulud to TeamPCP

The first Shai-Hulud wave proved the concept: a package-manager worm can spread without a traditional vulnerability. It used compromised npm maintainers, poisoned tarballs, lifecycle hooks, GitHub token abuse, and automated republishing. The second wave, Sha1-Hulud V2, expanded the blast radius to roughly 700 malicious package versions, 25,000+ attacker-created or abused GitHub repositories, and 37 affected organisations across analytics, Web3, API tooling, e-commerce, automation, and developer infrastructure. CyberScoop reported the November 2025 wave exposing more than 26,000 GitHub repositories in under 24 hours.

The V3.0 variant appears more contained in initial distribution but more mature in tradecraft: new loader names, removed dead-man switch, improved Windows/Bun handling, and a useful detection artefact in the c0nt3nts.json vs c9nt3nts.json filename mismatch. The newest Mini Shai-Hulud / TeamPCP-linked wave crosses into high-value projects and signed supply-chain workflows — TanStack, Mistral AI, Guardrails AI, UiPath, OpenSearch, and Bitwarden CLI — abusing OIDC tokens to publish with verifiable provenance.

Variant Evolution

VariantExecution HookPayload NamesKey MutationsDefender Implication
Shai-Hulud V1postinstallbundle.jsEstablishes worm viability; GitHub repo exfil with Shai-Hulud namingProves install-time RCE as propagation vector
Sha1-Hulud V2preinstallsetup_bun.js, bun_environment.jsEarlier execution window; CI-aware; cloud.json / truffleSecrets.json exfil; 26K repo exposure in <24hHigher CI yield; noisy exfil repos still present
Sha1-Hulud V3lifecycle -> Bunbun_installer.js, environment_source.jsRenamed loaders; removed dead-man switch; Windows Bun fix; Goldox-T3chs repo brand; c0nt3nts vs c9nt3nts mismatch IOCIOC rotation defeats hash-only detection
CanisterWormpostinstall (npm)CanisterWorm payloadDeployed alongside Trivy/KICS GitHub Actions wave; lateral npm propagation from CI accessSecurity scanners used as delivery vector
Mini Shai-Hulud / TeamPCPpreinstall, prepare, optional depsrouter_init.js, @tanstack/setupOIDC token abuse; Sigstore provenance; IDE hook injection (.claude, .vscode); P2P C2; 170 packages in <24h; PyPI crossingCVE-invisible; npm audit signatures passes; no SCA signal

Hardening Guidelines with  https://phoenix.security/phoenix-purple-ai-sast-sca-ai-generated-code/ 

Technical Anatomy

Bootstrap: Three Polymorphic Loaders

The worm ships three independent bootstrap paths. This is not redundancy — it is guaranteed execution coverage across the widest possible range of CI configurations and developer machines.

Loader 1 — JavaScript/Bun (primary): The npm package.json preinstall hook invokes setup.mjs, which downloads the Bun runtime for the exact platform from github.com/oven-sh/bun, then executes the 11-12 MB obfuscated JavaScript payload. Bun was chosen deliberately: most detection rules assume Node-only execution, and Bun’s performance allows a full credential sweep within a normal install-time window.

Loader 2 — Python (fallback): src/assets/PYTHON_LOADER.py implements a complete Python bootstrap activated via Python .pth site-packages hooks. Any Python interpreter startup triggers the payload — not just importing the compromised package, but any Python process at all. This is the mechanism used in the LiteLLM and Bitwarden compromises.

Loader 3 — Bash (tertiary): An encrypted BASH_LOADER payload stored in src/generated/index.ts provides a third execution path using only standard shell utilities. Three loaders across three runtimes means the worm survives CI environments with unusual toolchain configurations.

Credential Harvesting: The Worm’s Real Payload

The malware is not primarily destructive. It is a credential factory. The FileSystemService sweeps 100+ file paths across Linux, macOS, and Windows. Deep collection providers sweep cloud APIs, secret stores, and CI runner contexts.

Credential ClassTarget ExamplesWhy It Matters
Source controlGitHub PATs, GITHUB_TOKEN, GitHub App tokens, OIDC tokensRepo takeover, workflow injection, package publishing rights
Package registriesnpm tokens, PyPI credentials, OIDC publisher federationWorm propagation — each stolen token backdoors all packages that token can publish
CloudAWS access keys, Azure CLI cache, GCP service accounts, IMDS tokensCloud pivot and secret-manager enumeration
CI/CDGitHub Actions secrets, runner environment, build variablesTier-0 blast radius — everything the pipeline touches
KubernetesService account tokens, kubeconfig, cluster secrets, k3s configsRuntime and cluster-level control
Vault / secret storesHashiCorp Vault KV, AWS Secrets Manager, GCP Secret Manager, Azure Key VaultCentral exfiltration of all stored secrets in one sweep
Developer toolingSSH keys, .npmrc, .pypirc, .netrc, .env, shell history, AI assistant configsLocal developer compromise; persistent re-infection vector
Crypto / walletsBitcoin, Ethereum, Monero, Zcash keystores; Exodus, ElectrumDirect monetisation path

The AwsSsmService and AwsSecretsManagerService sweep all AWS SSM parameters and Secrets Manager entries across all regions using a full SigV4 credential resolution chain — environment variables, INI profiles, IRSA OIDC, ECS container metadata, and EC2 IMDS — whichever is available in the current context.

Critical Exploit Techniques

F-02sudo python3 Runner Secret Dumpsrc/providers/ghrunner/runner.ts:39-44 pipes an AES-256-GCM encrypted Python script to sudo python3 -c. The script reads Runner.Worker and Runner.Listener process memory, extracting every secret injected by GitHub Actions at runtime — including secrets marked as masked. The encryption keeps the script invisible to static analysis; it decrypts only at runtime, in memory. Consequence: masking secrets in workflow YAML does not protect them if the runner process is accessible. Rotating only npm tokens after this fires is insufficient — everything accessible to the runner must be treated as exposed.
F-03/04GitHub Actions CI Hijack: CodeQL Impersonation + Self-Cleaning Evidence. When a ghp_ token with workflow scope is found, the worm creates a branch named dependabot/github_actions/format/setup-formatter, commits a malicious workflow to .github/workflows/codeql_analysis.yml with committer identity github-advanced-security[bot]@users.noreply.github.com, waits for CI to execute and extract secrets via artifact, then deletes the branch and run logs. Three simultaneous layers of impersonation: Dependabot branch naming, GitHub CodeQL workflow path, GitHub Security bot committer identity. A developer reviewing recent commits would need to read commit content — not just metadata — to catch it.
F-09Public Token Extortion via Commit Message src/utils/config.ts:2-4 defines SEARCH_STRING as the literal string: IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner. When the worm commits exfiltrated data using the victim’s own token, this string is posted as a public commit message containing the victim’s token. This is not an oversight — it is an explicit extortion mechanism designed to deter credential rotation during incident response. Responders who revoke the token are warned the wiper will activate.
F-10Org Membership-Gated Wiper src/sender/github/gitHubSenderFactory.ts:100-105 gates the rm -rf ~/ destructive payload on whether the victim’s GitHub account has zero organisational memberships. Solo developers, freelancers, and open-source maintainers are specifically selected for data destruction. The logic is deliberate: no org membership correlates with no incident response process and no monitoring. Accounts with org membership trigger exfiltration without the wiper.
F-11OIDC Supply Chain with Cryptographically Valid Sigstore Provenance NPMOidcClient targets the opensearch-js release pipeline, stealing the GitHub OIDC token from ACTIONS_ID_TOKEN_REQUEST_URL, exchanging it for npm publish rights, generating a fully valid Sigstore bundle (ephemeral ECDSA P-256 keypair, Fulcio signing certificate, real Rekor transparency log entry), injecting @opensearch/setup as an optional dependency (pinned to attacker-controlled commit d446803f), and republishing. The provenance is not forged — it is genuinely signed using the victim CI’s identity. npm audit signatures returns a pass. Signed provenance does not prove benign code; it proves a compromised workflow produced the artifact.
F-12/13Three Bootstrap Loaders; Nine Encrypted Payloads JS/Bun, Python .pth, and Bash loaders ensure execution across radically different environments. Nine AES-256-GCM encrypted payloads are stored in src/generated/index.ts: config, task, DEADMAN_SWITCH, verify_key, claude_settings, python_util, PYTHON_LOADER, BASH_LOADER, and workflow. None are recoverable from the binary without the operator’s decryption key. String-level analysis of the production bundle surfaces no plaintext indicators.
F-14Raw Shell Injection via ${{ raw: command }}src/utils/shell.ts:20 uses Bun’s ${{ raw: command }} syntax, which bypasses Bun’s default shell escaping. This is the internal execution wrapper throughout the payload. Any attacker-controlled string reaching a shell execution point runs without sanitization.
F-15/16/1725+ CI Platforms; 100 Repos per Token; Full Org Secret Coverage src/utils/config.ts:53-148 detects 25+ CI platforms including GitHub, GitLab, Travis, CircleCI, Jenkins, Azure Pipelines, AWS CodeBuild, Buildkite, Netlify, Vercel, and more. When a ghp_ token is found, up to 100 writable repos are enumerated and org-level Actions secrets are swept across all accessible repos. The blast radius of a single compromised token is enormous.
F-19/20Signal Handler Suppression and TLS Verification Disabled SIGINT and SIGTERM handlers are set to no-op at startup — the process cannot be cleanly terminated. npm publish operations use rejectUnauthorized: false, disabling TLS certificate verification and evading network inspection. User-Agent is spoofed to npm/11.13.1 node/v24.10.0. Russian locale check (Intl, LC_ALL, LC_MESSAGES, LANGUAGE, LANG, Windows regional env) exits immediately — a classic nation-state operational security marker.

Operational Polymorphism

Sha1-Hulud is not polymorphic malware in the classic packed-binary sense. Call it operationally polymorphic supply-chain malware. It is not mutating encryption routines or rewriting opcodes. It is rotating the surface presentation of a stable kill chain.

Across waves, the following change: filenames, lifecycle hook names, execution engines (Node, Bun, Python, Bash), package paths, exfiltration repo descriptions, exfil file names, staging methods, C2 fallback patterns, persistence locations, and campaign branding. What stays constant across every wave: install-time execution → credential theft → GitHub/npm/cloud abuse → exfiltration → persistence → package republishing.

This mutation pattern defeats brittle detection that only looks for one hash, one filename, or one malicious package version. A defender looking only for bundle.js misses setup_bun.js. A defender looking only for setup_bun.js misses router_init.js. A defender looking only for unsigned packages misses OIDC-signed malicious releases. Each wave is designed to invalidate the indicators published about the previous wave.

Exfiltration Architecture: Four-Level Fallback

The malware is designed not to fail closed. If one exfiltration path breaks, it falls back to the next without operator intervention.

PriorityChannelMechanismFallback Trigger
1git-tanstack.com:443/routerHTTPS POST — AES-256-GCM + RSA-OAEP encrypted payloadPrimary — attempted first
2Signed-commit C2 discoverySearch thebeautifulmarchoftime repo, RSA-verify commit message, extract domainPrimary unreachable
3Attacker GitHub repo (attacker token)Double-base64 encoded token from commit; creates Dune-themed repoC2 discovery fails
4Victim’s own GitHub accountHarvested ghp_/gho_ token; creates repo; commits data; extortion message in commit bodyAll prior channels unavailable

Earlier waves also used webhook-style exfiltration to webhook.site endpoints and GitHub Actions artifacts. The Telnyx wave introduced Session P2P network exfiltration via filev2.getsession.org alongside the steganographic WAV delivery channel.

Persistence Mechanisms

MechanismImplementationTrigger Condition
.claude/ + .vscode/ repo injectionMalware binary to .claude/<SCRIPT_NAME>; encrypted loaders to .claude/setup.mjs, .vscode/setup.mjs, .vscode/tasks.json; committed to every branch of every writable repoVS Code workspace open; Claude Code invocation
GitHub Actions workflow implantWorkflow injected as dependabot/github_actions/format/setup-formatter branch; committer impersonates github-advanced-security[bot]; self-deletes after secret extractionghp_ token with workflow scope found
Self-hosted runner registration (V2)Persistent runner named SHA1HULUD registered; triggered by .github/workflows/discussion.yaml via GitHub Discussions eventsGitHub App token found; RCE bridge to internal infra
Python .pth site executionlitellm_init.pth in site-packages imports loader on every Python startupCompromised PyPI package installed
systemd user service~/.config/sysmon/sysmon.py registered as systemd serviceLiteLLM/TeamPCP PyPI wave; Linux hosts
Windows Startup folderPE extracted from WAV file via steganography written as msbuild.exe to user Startup folderTelnyx wave; Windows hosts; no admin rights required
Package republishingBackdoored versions in lockfiles, artifact caches, internal registries, Docker image layers persist after upstream cleanupAny npm token with bypass_2fa + package:write

Package caches and build images are persistence locations. Cleaning the npm registry upstream does not remove infected versions already pinned in lockfiles or cached in Artifactory/Nexus layers. Treat any internal registry that pulled packages during affected windows as potentially contaminated.

IOC Catalogue

File and Payload IOCs

IndicatorAssociated WaveNotes
bundle.jsV1Original npm payload
setup_bun.jsV2V2 Bun setup loader
bun_environment.jsV2V2 environment payload
bun_installer.jsV3V3 renamed loader
environment_source.jsV3V3 main payload
router_init.jsMini Shai-Hulud / TeamPCPTanStack/Mistral wave payload
router_runtime.jsPyPI / Lightning-linkedReported by SafeDep; PyPI crossing
cloud.jsonV2Exfil credential snapshot
contents.jsonV2Exfil snapshot
environment.jsonV2Environment dump
truffleSecrets.jsonV2Secret scan output
3nvir0nm3nt.jsonV3Renamed exfil file
cl0vd.jsonV3Renamed exfil file
pigS3cr3ts.jsonV3Renamed exfil file
c0nt3nts.json (fetch) vs c9nt3nts.json (save)V3Detection artefact — fetch and save use different filenames
.github/workflows/shai-hulud-workflow.ymlV1/V2Workflow persistence
.github/workflows/discussion.yamlV2Self-hosted runner persistence via Discussions trigger
.vscode/tasks.jsonMini Shai-HuludIDE persistence — runs on VS Code workspace open
.claude/settings.jsonMini Shai-HuludAI assistant config hijack
.claude/setup.mjsMini Shai-HuludAI assistant bootstrap loader
litellm_init.pthLiteLLM / TeamPCP PyPIPython import hook persistence
~/.config/sysmon/sysmon.pyLiteLLM / TeamPCPLinux systemd persistence agent
msbuild.exe in Startup folderTelnyx waveWindows boot persistence — no admin required
SHA-256: 46faab8ab153fae6e80e7cca38eab363075bb524edd79e42269217a083628f09V1Frequently cited V1 payload hash

Repository and Branch IOCs

IndicatorMeaning
Repo name/description contains: Shai-HuludV1/V2 exfil branding — public repos created in victim accounts
Repo description: Sha1-Hulud: The Second ComingV2 campaign repo description
Repo description: Goldox-T3chs: Only Happy GirlV3 campaign repo description — IOC rotation
Repo description: A Mini Shai-Hulud has AppearedMini Shai-Hulud exfil repo marker
Repo names: sardaukar-*, sandworm-* in victim accountsProcedurally generated Dune-themed exfil repo names
Branch: shai-huludPersistence / staging indicator in victim repos
Branch: dependabot/github_actions/format/setup-formatterGitHub Actions workflow injection — Dependabot impersonation
Self-hosted runner named SHA1HULUDV2 persistent runner registration
Commit author: github-advanced-security[bot]@ on non-CodeQL commitsWorkflow hijack indicator
Commit message containing IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwnerExtortion marker + exposed victim token

Domain and Infrastructure IOCs

IndicatorContextCampaign
git-tanstack.comPrimary C2 exfiltration endpointMini Shai-Hulud / TeamPCP
audit.checkmarx[.]cxSecondary exfil endpoint (typosquat of legitimate Checkmarx domain)Bitwarden CLI wave
checkmarx[.]zonePersistence polling domain — LiteLLM variant polls every 50 minutesLiteLLM / TeamPCP PyPI
filev2.getsession.orgSession P2P network C2Telnyx wave
89.36.224.5C2 IPvelora-dex/sdk incident
metrics-trustwallet[.]comRelated infrastructureV1/V2 era
m.fasterxml[.]orgTyposquatted Maven-related domainV3 context
webhook.site endpointsEarlier exfil path for secretsV1/V2 waves
thebeautifulmarchoftime (GitHub repo)Signed-commit C2 domain discovery sourceMini Shai-Hulud

Use domain IOCs with care in the article: several are campaign-specific and should not be treated as universal across every Shai-Hulud variant. Confirm campaign context before blocking at the network layer.

MITRE ATT&CK Mapping

TechniqueIDImplementation
Supply Chain CompromiseT1195.001npm/PyPI package backdooring via stolen tokens and OIDC federation
Command and Scripting InterpreterT1059.004Bash loader; shell.ts raw injection; Python .pth import hook
Boot or Logon Autostart: XDG/systemdT1547.013systemd user service persistence (LiteLLM/TeamPCP wave)
Boot or Logon Autostart: Startup FolderT1547.001Windows Startup folder (Telnyx wave — no admin required)
Event Triggered ExecutionT1546GitHub Actions workflows triggered by push/discussion; IDE task hooks
Hijack Execution Flow: .pthT1574Python site-packages .pth execution on every interpreter startup
Valid Accounts: Cloud AccountsT1078.004OIDC token exchange for npm publish; cloud credential abuse
Steal Application Access TokenT1528GitHub OIDC token from ACTIONS_ID_TOKEN_REQUEST_URL; runner process memory
Credentials from FilesT1552.001100+ filesystem hotspots across Linux/macOS/Windows
Credentials from Password StoresT1555Bitwarden CLI backdoor; crypto wallet sweep; Vault/K8s secret APIs
Obfuscated Files / InformationT1027AES-256-GCM encrypted payload constants; JS obfuscation; scramble()
SteganographyT1027.003WAV-embedded PE delivery (Telnyx wave)
Abuse Elevation Control MechanismT1548sudo python3 runner secret dump (F-02)
Software Deployment ToolsT1072npm publish / PyPI upload abused as lateral movement and propagation
Exfiltration Over Web ServiceT1567.002GitHub repo commits; GitHub Actions artifacts; P2P Session network
Data Encrypted for ImpactT1486rm -rf ~/ wiper gated on org membership (F-10)
ImpersonationT1656Dependabot + CodeQL + GitHub Security bot commit identity spoofing

Detection Engineering

Package Scan Signals

Standard CVE-based SCA has zero surface against this campaign. These are the detection primitives that work:

  1. Lifecycle script delta: flag packages where preinstall, postinstall, or prepare was added or changed between versions. This single rule would have caught every Shai-Hulud wave at the package level.
  2. External binary download during install: alert on npm install processes that spawn curl, wget, or fetch connections to github.com/oven-sh/bun or any non-registry domain.
  3. Tarball-vs-source divergence: compare the published npm tarball content against the corresponding GitHub tag commit tree. Every TeamPCP-compromised package shows files in the registry that are absent from the source repo.
  4. Optional dependency pointing to unfamiliar setup packages: @opensearch/setup, @tanstack/setup, and similar patterns in optionalDependencies should trigger review.
  5. Filename patterns in package contents: flag any package containing bundle.js, setup_bun.js, bun_installer.js, bun_environment.js, router_init.js, or environment_source.js.

GitHub Hunting Queries

Search organisation repositories for:

repo.description: Shai-Hulud OR Sha1-Hulud OR Goldox-T3chs OR Mini Shai-Hulud

branch: shai-hulud OR dependabot/github_actions/format/setup-formatter

workflow path: .github/workflows/shai-hulud-workflow.yml

workflow path: .github/workflows/discussion.yaml

workflow path: .github/workflows/codeql_analysis.yml (verify against expected CodeQL config)

committer: github-advanced-security[bot] (verify against real CodeQL scan events)

self-hosted runner name: SHA1HULUD

repo visibility changed private -> public (unexpected)

CI/CD Alerts

  • npm publish –force from CI runners outside expected release workflows
  • Bun execution in jobs that do not normally use Bun — especially during npm install
  • OIDC token requests (ACTIONS_ID_TOKEN_REQUEST_URL access) outside release workflows
  • GitHub Actions cache writes from pull_request_target workflows checking out untrusted forks
  • New workflow files committed by bot identities not matching expected automation
  • Workflow run logs deleted shortly after completion
  • Sudden publishing of many patch versions across a namespace in a short window

Cloud and Secret Store Alerts

  • AWS access keys first used from CI identities shortly after a suspicious install job
  • AWS Secrets Manager or SSM ListSecrets/GetSecretValue calls from build agents that do not normally read secrets
  • GCP Secret Manager access from build agents outside production deploy workflows
  • Kubernetes API secret enumeration (list secrets across all namespaces) from non-ops identities
  • HashiCorp Vault KV list/read bursts from CI runner IPs

Endpoint / Developer Machine Signals

Search developer workstations and CI nodes for:

~/.claude/  (unexpected files beyond normal Claude config)

~/.claude/settings.json  (compare against expected content)

~/.claude/setup.mjs  (should not exist in normal Claude Code installation)

.vscode/tasks.json  (in repo working directory — inspect content for base64 or external fetch)

.vscode/setup.mjs  (in repo working directory — should not exist)

cloud.json / contents.json / environment.json / truffleSecrets.json

3nvir0nm3nt.json / cl0vd.json / pigS3cr3ts.json

litellm_init.pth in any Python site-packages directory

msbuild.exe in %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup

Remediation Guidance

Immediate Containment

ActionOwnerReason
Freeze dependency upgrades for npm/PyPIPlatform / DevOpsStop pulling newly infected versions during the active campaign window
Block direct npm/PyPI from CI; route through internal proxyPlatformForce registry inspection; enable quarantine period
Disable lifecycle scripts where feasible (ignore-scripts=true in CI .npmrc)Engineering / CI ownersBreaks install-time execution at the first hop for every Shai-Hulud variant
Quarantine affected runners immediatelyDevOps / SOCAssume everything accessible to the runner is exposed
Revoke and rotate all GitHub PATs, npm tokens, cloud keys, PyPI tokensIAM / PlatformTokens are the worm’s primary propagation fuel
Audit GitHub repo creation and repo visibility changes (private → public)GitHub org adminDetect exfil repositories created in victim accounts
Remove suspicious workflows and self-hosted runnersDevOpsKill CI and runner persistence before next triggered job
Purge npm/PyPI package caches and rebuild all container imagesPlatformRemove cached poisoned artifacts from internal registries and Docker layers

Medium-Term Controls

ControlRationale
Require lockfiles and exact versions across all projectsPrevent silent patch-version compromise — Shai-Hulud always bumps the patch version
Enforce registry quarantine or cooldown window (24-48h)Both Shai-Hulud and Mini Shai-Hulud had short, intense exposure windows — delay breaks the propagation chain
Diff package tarball vs source repo in CI pipelineDetect hidden payloads not present in Git — primary detection signal for every TeamPCP package
Require human approval for new lifecycle scriptsLifecycle hooks are execution primitives; treat them as code review requiring sign-off
Protect pull_request_target workflows from untrusted code checkoutPin to trusted authors or remove id-token: write from all untrusted-fork-accessible workflows
Restrict OIDC audiences and Trusted Publisher mappings to specific workflow file pathsReduce OIDC blast radius — Mini Shai-Hulud abused a namespace-wide OIDC binding
Monitor GitHub Actions cache writes from PR contextsCache poisoning enables re-execution without code changes in the PR
Use short-lived, scoped publishing tokens; rotate on scheduleLimits worm propagation radius per stolen token
Alert on package publishing outside expected release workflowsDetects maintainer token abuse and CI identity compromise immediately
Inventory packages owned by each team before compromiseKnow your propagation surface; map token → packages → downstream consumers

Phoenix Security Recommendations

The Sha1-Hulud / TeamPCP campaign breaks the scan-and-patch model at every layer. The issue is not vulnerable dependency X — it is malicious dependency intake, poisoned package versions, trusted publisher abuse, CI identity compromise, cloud secret exposure, developer workstation persistence, hidden workflow implants, repo visibility changes, internal registry contamination, and cached malicious artifacts. Recovery is not patching a package. It requires pinning, proxying, credential rotation, workflow removal, runner cleanup, and reachability-driven triage.

Phoenix Security addresses this through controls that operate below the CVE layer:

  • Tarball-vs-source divergence detection: Phoenix correlates published package tarballs against corresponding source repository commits, surfacing packages where the registry artifact diverges from what the maintainer published — the primary and often only detection signal across every TeamPCP-compromised package.
  • Lifecycle script change detection: Phoenix flags new or changed preinstall/postinstall/prepare entries across the dependency graph, triggering review before the package reaches a CI runner.
  • OIDC and Actions configuration auditing: Phoenix maps pull_request_target workflows with sensitive permission grants across your entire GitHub organisation, surfacing configurations that match the TeamPCP initial access pattern before compromise occurs.
  • Reachability-driven blast radius analysis: Rather than flagging every package with a lifecycle hook, Phoenix identifies which hooks are reachable in your specific dependency graph and execution context, then maps the downstream credential and package publishing exposure for each.
  • Remediation campaign tracking: When a compromise is confirmed or suspected, Phoenix creates a remediation campaign mapping every affected repository, assigns ownership to the responsible team, and tracks fix verification against runtime exposure — rather than leaving incident response as ad-hoc manual work across distributed teams.
  • Developer tooling treated as Tier-0: Phoenix monitors the supply chain posture of Trivy, KICS, Bitwarden CLI, LiteLLM, and similar tools with the same controls applied to production dependencies. The Trivy and KICS GitHub Actions compromises demonstrate that security tooling is not trusted infrastructure — it is a high-value attack surface.

The strong positioning for ASPM: Sha1-Hulud is the case study for remediation-aware exposure management. The winning control is not a bigger vulnerability list. It is code-to-cloud attribution, package-version provenance, CI workflow visibility, owner mapping, and blast-radius reduction.

Hardening Guide: Code-Mapped Defenses

Every control below is mapped to a specific source file and line in the Shai-Hulud-Open-Source reference implementation. Attack-vector claims are validated from code. Some platform-configuration recommendations (exact GitHub settings UI paths, audit event field names) are operationally well-grounded but are not provable from the repo alone — those are marked accordingly.

The three controls that stop this malware with minimal engineering effort:

ControlBlocksCode ReferenceEffort
ignore-scripts=true in .npmrcnpm lifecycle bootstrap — no postinstall = no executionsrc/assets/config.mjs:176-199Minutes
Remove sudo from CI runnerssudo python3 runner secret dump — the single most powerful harvestersrc/providers/ghrunner/runner.ts:39-45Hours
Branch protection + require signed commits on *ReadmeUpdater entire persistence pipeline — commits unsigned, blocked by policysrc/mutator/branch/index.ts:47-63Hours

Note on the ignore-scripts claim: this is the highest-value single control against the npm bootstrap path shown in config.mjs. It is not the only possible execution path once a payload is already resident — GitHub Actions abuse, branch mutation, and npm republishing operate independently once the worm has run once. Treat it as the essential first gate, not a universal kill switch.

Layer 1: npm Supply-Chain (Entry Point)

The malware enters via npm postinstall (src/assets/config.mjs:176-199), downloads the Bun runtime from github.com/oven-sh/bun, and executes the obfuscated payload. Blocking this execution path stops the worm before any credential harvesting begins.

ControlWhat It BlocksHow to ImplementValidated
ignore-scripts=true in .npmrcpostinstall hook entirelyCommit .npmrc with ignore-scripts=true to every repo; enforce in CI with npm ci –ignore-scriptsValidated — config.mjs:176
npm ci (not npm install) in CITampered package-lock.jsonnpm ci fails if lockfile differs from package.json — prevents silent version driftValidated — mutator bumps patch version src/mutator/npm/index.ts:71
Block objects.githubusercontent.com from CI egressBun runtime downloadEgress firewall: block objects.githubusercontent.com from runner IPs — download is required before payload executesValidated — config.mjs:29-44
Private registry proxy (Artifactory / Nexus)Direct registry.npmjs.org access and backdoored tarball distributionRoute all npm traffic through internal proxy; scan tarballs before caching; quarantine period minimum 24-48hInferred from mutator publish path src/mutator/npm/publish.ts:113
Block registry.npmjs.org PUT/POST from CInpm package backdooringEgress firewall: allow GET to npm registry; block PUT and POST — republish requires PUTValidated — src/mutator/npm/publish.ts:113-159
Disable bypass_2fa on npm automation tokensnpm token backdooringMalware specifically filters for bypass_2fa=true tokens before attempting republish; disable on all automation tokensValidated — src/mutator/npm/tokenCheck.ts:9-125

Layer 2: GitHub Token Scope Hardening

The malware checks for ghp_, gho_, ghs_, and npm_ tokens (src/providers/ghrunner/runner.ts:14-18) and requires repo scope before initialising the GitHub exfiltration sender (src/sender/github/gitHubSenderFactory.ts:81-83).

ControlWhat It BlocksGrounded InValidated
Fine-grained PATs only; no contents:write unless requiredGitHub repo creation and commit-based exfiltrationSender requires repo-capable token via hasRepoScope check — narrower scopes break the sender initialisationValidated — gitHubSenderFactory.ts:81-83
Token expiry <= 24h on all automation PATsLong-lived tokens harvested from filesystemShort TTL means a harvested token is already expired before the operator can use itValidated — filesystem.ts sweeps .git-credentials and .netrc
No workflow scope on PATs not used for workflow managementGitHub Actions workflow injectionWorkflow injection proceeds only against tokens with workflow write accessValidated as inference — workflow.ts:50-78
GitHub token permission audit: revoke admin:org and secrets:read not explicitly requiredOrg secret enumeration across all reposMalware enumerates org secrets via Actions API using harvested tokensValidated — src/providers/actions/secrets.ts:36-47
Secret scanning push protection enabled on all reposToken committed to public GitHub reposMalware commits token-bearing data in commit messages when includeToken is setValidated — githubSender.ts:156-158; exact push protection behavior is platform-level

Layer 3: GitHub Actions Hardening

The most sophisticated attack surface. The malware injects a fake CodeQL workflow (src/providers/actions/workflow.ts:13), impersonates github-advanced-security[bot] (workflow.ts:71-75), exfiltrates secrets via artifact download, and self-deletes the branch and run logs (workflow.ts:177-186).

Hardened workflow permissions template — apply as org-level default:

permissions:

  contents: read        # NOT write

  id-token: none        # Override per-job only when signing is required

  actions: none

  secrets: none         # No ambient secret enumeration

ControlWhat It BlocksCode ReferenceValidated
Branch protection: require PR for all branches (* wildcard)Direct push to dependabot/github_actions/format/setup-formatter without reviewsrc/providers/actions/workflow.ts:56-62Validated — branch creation and direct push are the injection mechanism
Pin all Actions to full commit SHA not floating tagsMalicious action tag hijacking (Trivy/KICS wave)Trivy/KICS wave: aquasecurity/trivy-action@v0.20.0 vs full SHAValidated from TeamPCP campaign (not this repo)
Require workflow approval for first-time and outside contributorsAny injected workflow from compromised fork or new accountsrc/providers/actions/workflow.ts:50-77Validated as reasonable platform guidance
Block sudo on CI runners (sudoers policy or hardened runner image)sudo python3 runner secret dump — the entire GitHubRunner harvest pathsrc/providers/ghrunner/runner.ts:39-45Validated — entire runner dump depends on sudo python3
Restrict id-token: write to the specific job that needs itOIDC token stolen for Sigstore provenance and npm publishsrc/mutator/npmoidc/provenance.ts:173-199Validated — OIDC token extraction requires id-token: write permission
Use ephemeral self-hosted runners (–ephemeral flag)Persistence between workflow runs on self-hosted runnersSHA1HULUD runner registration in V2 waveValidated from campaign analysis (not this repo code)
Stream GitHub audit logs to SIEMSelf-deleting workflow runs — API delete removes UI visibility but audit log entry is durablesrc/providers/actions/workflow.ts:177-186Partially validated — exact audit event names are platform-level

Layer 4: Git Repository Hardening

ReadmeUpdater (src/mutator/branch/index.ts:34-63) commits to every branch using GitHub GraphQL createCommitOnBranch. It explicitly avoids dependabot/** and copilot/** branches but attempts all others. Commit headline is hardcoded as ‘chore: update dependencies’ with co-author claude@users.noreply.github.com.

ControlWhat It BlocksImplementationValidated
Branch protection on ALL branches (* wildcard, require 1 reviewer)Commit to any unprotected branch without PRGitHub repo Settings > Branches > Apply protection to * patternValidated — malware pushes directly without PR flow
Require signed commits (GPG or SSH)Unsigned disguised dependency-update commitsSettings > Branches > Require signed commits. ReadmeUpdater does not implement commit signing in sourceValidated — no signing code found in src/mutator/branch/index.ts; the ‘has no signing key’ phrasing is softened — no key found in code but cannot assert globally
CODEOWNERS: .claude/ and .vscode/ require @security-team review.claude/ and .vscode/ file injection reaching main without reviewAdd to CODEOWNERS: /.claude/ @security-team   /.vscode/tasks.json @security-teamValidated — injected files are explicit in src/mutator/branch/index.ts:34-40
Alert on co-author claude@users.noreply.github.com on non-Claude-Code commitsDisguise co-author used to blend into repos that use Claude CodeSIEM: GitHub audit git.push events where commit trailer contains claude@users.noreply.github.comValidated — co-author hardcoded: src/mutator/branch/index.ts:58-63
GitHub Rulesets (Enterprise): block push of .claude/** without approval.claude/ injection into protected branchesRepo Rulesets > File path restrictions: .claude/**Reasonable platform guidance — not directly evidenced in repo code

Layer 5: Secret Management Hardening

The malware sweeps 100+ filesystem hotspots and calls AWS SSM, Secrets Manager, Kubernetes, and HashiCorp Vault APIs directly. All of these providers are validated in source code.

ControlWhat It BlocksGrounded In
Never write ~/.aws/credentials; use IAM roles, IRSA, or instance metadata insteadStatic AWS credential file harvestsrc/providers/filesystem/filesystem.ts — sweeps ~/.aws/credentials explicitly
AWS IAM: deny ssm:GetParametersByPath and secretsmanager:ListSecrets except from specific VPC endpointsFull SSM and Secrets Manager enumeration across all regionssrc/providers/aws/ssm.ts:17-93; src/providers/aws/secretsManager.ts:13-180 — sweeps all default regions
Kubernetes RBAC: ServiceAccount must not have get/list on secrets cluster-wide; use namespace-scoped rolesAll-namespace Kubernetes secret dumpsrc/providers/kubernetes/kubernetes.ts:166-213 — lists namespaces then reads secrets in each
HashiCorp Vault: enable audit logging; token TTL <= 1h; enable max_lease_ttlFull Vault KV sweep across all mounts (v1 and v2)src/providers/vault/vault-secrets.ts:195-220 — enumerates all KV mounts and reads all keys
Remove gh CLI from CI runner images; use GITHUB_TOKEN env var at minimum scopeShellService execSync(‘gh auth token’) harvestsrc/providers/devtool/devtool.ts:19-29 — explicitly runs gh auth token
Encrypt developer home directories (FileVault on macOS, LUKS on Linux)SSH keys, git credentials, shell history, crypto wallet files at restsrc/providers/filesystem/filesystem.ts — sweeps ~/.ssh, ~/.bash_history, wallet files

Layer 6: Network Egress Controls

The malware uses a four-level exfiltration fallback chain. Blocking all outbound from CI runners except allowlisted destinations collapses every channel simultaneously.

ControlWhat It BlocksCode Reference
Block git-tanstack.com (DNS sinkhole + firewall rule)Primary C2 exfiltration endpointsrc/index.ts:95-100
Block objects.githubusercontent.com from CI runnersBun runtime download — required before any payload executessrc/assets/config.mjs:29-44
Block registry.npmjs.org PUT/POST from CInpm package backdooring via republishsrc/mutator/npm/publish.ts:113-159
Block fulcio.sigstore.dev and rekor.sigstore.dev except from dedicated signing infraSigstore provenance forgery using victim CI OIDC identitysrc/mutator/npmoidc/provenance.ts:227-231; provenance.ts:288-295
Alert on DNS queries to domains registered < 30 days ago from CI runnersSigned-commit C2 discovery — operator can rotate C2 domain via a new commitsrc/sender/domain/domainSenderFactory.ts:26-47
TLS inspection on CI egressAES-256-GCM encrypted exfiltration to C2 (note: malware disables TLS verification on npm publish but not C2)src/mutator/npm/publish.ts:157; src/index.ts:95-100
Block api.github.com from production systems (not CI)GitHub commit-based exfiltration fallbacksrc/sender/github/githubSender.ts:108-121 — this is a context-specific recommendation, not universal

Layer 7: SIEM Detection Signals

Nine behavioral fingerprints grounded directly in source. The IfYouRevokeThisToken commit message and the dependabot/github_actions/format/* branch pattern are the highest-fidelity signals — they are hardcoded strings in the malware with no operational reason to appear in legitimate automation.

SignalSource (Code)SeverityDetection Query
Branch created matching dependabot/github_actions/format/* by non-Dependabot actorworkflow.ts:10-11CRITICALGitHub audit: ref=branch AND ref LIKE dependabot/github_actions/format/% AND actor != dependabot[bot]
Workflow file .github/workflows/codeql_analysis.yml created/modified by non-GitHub actorworkflow.ts:13CRITICALGitHub audit: action=workflows.created AND path LIKE *codeql_analysis* AND actor != github-advanced-security[bot]
Commit message containing IfYouRevokeThisTokensrc/utils/config.ts:2-4CRITICALGitHub audit + git log: message CONTAINS IfYouRevokeThisToken — this string has no legitimate use
sudo python3 spawned from npm postinstall or Bun contextrunner.ts:39CRITICALauditd: execve sudo python3 WHERE parent process is node, npm, or bun
rm -rf ~/ spawned from bash -sgithubSender.ts:60,89CRITICALauditd: execve rm -rf WHERE parent is bash with -s flag AND grandparent is bun
Commit co-authored by claude@users.noreply.github.com on non-Claude-Code commitsbranch/index.ts:58-63HIGHGitHub audit: action=git.push AND commit trailer CONTAINS claude@users.noreply.github.com
npm patch version bump with new preinstall: node setup.mjs in same publishnpm/index.ts:68-70HIGHnpm publish log: version bump AND preinstall script added in same event
Mass branch commits >5 branches, same commit message, within 60 secondsbranch/index.ts:74,181HIGHGitHub audit: action=git.push COUNT > 5 WHERE message=’chore: update dependencies’ WITHIN 60s
Outbound DNS/HTTPS to git-tanstack.com from CI runnerssrc/index.ts:95-100CRITICALFirewall/DNS: any query or connection to git-tanstack.com from runner IP ranges
.claude/ or .vscode/tasks.json added in same commit as binary blobbranch/index.ts:34-40HIGHGit hook or SIEM: commit diff contains .claude/ path AND binary file in same tree

Hardening Priority Matrix

PriorityControlAttack Surface BlockedImplementation Effort
P0 — Criticalignore-scripts=true in .npmrcnpm lifecycle bootstrap (config.mjs:176) — no execution at allMinutes
P0 — CriticalBlock sudo on CI runnerssudo python3 runner dump (runner.ts:39) — entire GitHubRunner harvest path goneHours
P0 — CriticalBranch protection + signed commits on * (all branches)ReadmeUpdater persistence pipeline (branch/index.ts:47) — branches become write-protectedHours
P0 — CriticalEgress block: git-tanstack.com + objects.githubusercontent.comPrimary C2 + Bun binary download (config.mjs:29-44) — payload cannot download or phone homeMinutes
P1 — HighFine-grained PATs, no workflow scope, <= 24h expiryGitHub sender (gitHubSenderFactory.ts:81) + workflow injectionDays
P1 — HighDisable bypass_2fa on npm automation tokensnpm backdooring (tokenCheck.ts:9-125) — malware filters for this flag specificallyHours
P1 — HighGITHUB_TOKEN: permissions: read-all as org defaultWorkflow injection and org secret enumerationHours
P1 — HighCODEOWNERS for .claude/ and .vscode/IDE file injection persistence (branch/index.ts:34-40)Minutes
P2 — MediumAWS IAM: deny ssm:GetParameter* without VPC endpointAWS SSM and Secrets Manager full dump (aws/ssm.ts)Days
P2 — MediumK8s RBAC: no secrets:list or secrets:get cluster-wide for workloadsAll-namespace Kubernetes secret dump (kubernetes.ts:166)Days
P2 — MediumSIEM rules for all 10 behavioral signals aboveDetection after successful compromiseDays
P2 — MediumVault audit logging + token TTL <= 1hVault KV sweep (vault-secrets.ts:195)Hours
P3 — HardeningTLS inspection on CI egressEncrypted C2 exfiltration (C2 at git-tanstack.com:443)Weeks
P3 — HardeningPrivate npm registry proxy with tarball scanningBackdoored package distribution; tarball-vs-source divergence detectionWeeks

The results are clear:

  • Bazaarvoice saved $6.3M in developer time and for teams removed critical in the first weeks of adoption
  • ClearBank cut critical container vulnerabilities by 96–99% and reclaimed 4 hours per engineer per week.
  • A global AdTech company saved an equivalent of 1.5M in development hours and reduced SCA-to-container noise by 82.4%
  • Optimizely has been able to act on vulnerabilities sitting on the backlog.

👉 Book a demo today

Or learn how Phoenix Security slashed millions in wasted dev time for fintech, retail, and adtech leaders.

Fix with remediation. Don’t chase ghost vulnerabilities

  • Mini Shai-Hulud: TanStack OIDC Compromise — https://phoenix.security/mini-shai-hulud-teampcp-tanstack/
  • Mini Shai-Hulud: SAP CAP/MBT npm Packages — https://phoenix.security/mini-shai-hulud-sap-cap-mbt-npm-supply-chain-bun-credential-stealer/
  • Bitwarden CLI: 93-Minute npm Window — https://phoenix.security/bitwarden-cli-backdoored-shai-hulud-returns-through-a-93-minute-npm-window/
  • Axios Supply Chain RAT — https://phoenix.security/axios-supply-chain-compromise-npm-rat-2026/
  • TeamPCP Telnyx PyPI: WAV Steganography — https://phoenix.security/teampcp-telnyx-pypi-supply-chain-wav-steganography-windows-persistence/
  • TeamPCP LiteLLM PyPI — https://phoenix.security/teampcp-litellm-supply-chain-compromise-pypi-credential-stealer-kubernetes/
  • TeamPCP: Trivy + Checkmarx + GitHub Actions — https://phoenix.security/teampcp-supply-chain-attack-trivy-checkmarx-github-actions-npm-canisterworm/
  • Trivy Supply Chain Compromise — https://phoenix.security/trivy-supply-chain-compromise-teampcp-weaponised-scanner-ongoing-attack/
  • Sandworm Mode: Original npm Worm — https://phoenix.security/sandworm-mode-npm-supply-chain-worm/
  • Sha1-Hulud v3 — https://phoenix.security/sha1-hulud-v3-npm-supply-chain-attack/
  • npm Sha1-Hulud Explained — https://phoenix.security/npm-sha1-hulud-supply-chain-compromise-explained/

External References

  1. Shai-Hulud Open Source Reference Implementation: https://github.com/g00dfe11ow/Shai-Hulud-Open-Source
  2. StepSecurity — Mini Shai-Hulud Self-Spreading Supply Chain Attack: https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem
  3. Palo Alto Unit 42 — npm Supply Chain Attack (Sha1-Hulud): https://unit42.paloaltonetworks.com/npm-supply-chain-attack/
  4. Kaspersky — Critical Supply Chain Attack: Trivy, LiteLLM, Checkmarx, TeamPCP: https://www.kaspersky.com/blog/critical-supply-chain-attack-trivy-litellm-checkmarx-teampcp/55510/
  5. Wiz — TeamPCP KICS GitHub Action Compromise: https://www.wiz.io/blog/teampcp-attack-kics-github-action
  6. Wiz — Mini Shai-Hulud SAP npm: https://www.wiz.io/blog/mini-shai-hulud-supply-chain-sap-npm
  7. Trend Micro — TeamPCP Telnyx Attack: https://www.trendmicro.com/en/research/26/c/teampcp-telnyx-attack-marks-a-shift-in-tactics.html
  8. HexaStrike — Telnyx Python SDK Compromise: https://hexastrike.com/resources/blog/threat-intelligence/ringing-in-chaos-how-teampcp-weaponized-the-telnyx-python-sdk/
  9. SANS ISC — LiteLLM PyPI Compromise: https://isc.sans.edu/diary/32838
  10. Endor Labs — Mini Shai-Hulud SAP Developer Packages: https://www.endorlabs.com/learn/mini-shai-hulud-npm-worm-hits-sap-developer-packages
  11. OX Security — Shai-Hulud 170 Packages: https://www.ox.security/blog/shai-hulud-here-we-go-again-170-packages-hit-across-npm-pypi/
  12. Palo Alto — Bitwarden CLI Supply Chain Attack: https://www.paloaltonetworks.com/blog/cloud-security/bitwardencli-supply-chain-attack/
  13. Elastic Security — Axios One RAT to Rule Them All: https://www.elastic.co/security-labs/axios-one-rat-to-rule-them-all
  14. Rami McCarthy — TeamPCP Campaign Overview: https://ramimac.me/teampcp/
  15. Snyk — Trivy GitHub Actions Supply Chain Compromise: https://snyk.io/articles/trivy-github-actions-supply-chain-compromise/
  16. The Hacker News — SAP npm Packages Mini Shai-Hulud: https://thehackernews.com/2026/04/sap-npm-packages-compromised-by-mini.html
  17. CyberScoop — November 2025 Wave: 26,000 GitHub Repositories Exposed
  18. SafeDep — Shai-Hulud PyPI Crossing via Lightning Package: SafeDep Research Blog

Francesco is an internationally renowned public speaker, with multiple interviews in high-profile publications (eg. Forbes), and an author of numerous books and articles, who utilises his platform to evangelize the importance of Cloud security and cutting-edge technologies on a global scale.

Discuss this blog with our community on Slack

Join our AppSec Phoenix community on Slack to discuss this blog and other news with our professional security team

From our Blog

TeamPCP’s Mini Shai-Hulud worm hit 170 npm packages across TanStack, OpenSearch, and Mistral AI via OIDC token theft. Full IOCs, detection, and remediation.
Francesco Cipollone
A coordinated npm supply chain attack hit SAP’s Cloud Application Programming Model toolchain on April 29, 2026, branding itself “Mini Shai-Hulud.” Four packages totalling 570,000 weekly downloads were poisoned in a 2-hour window. The payload uses Bun as a runtime to evade Node.js detection, pulls 134 credential paths from infected hosts, dumps GitHub Actions runner memory, and persists through Claude Code SessionStart hooks and VS Code tasks.json folderOpen triggers. Over 1,197 victim repositories were live on GitHub within hours. Zero CVEs assigned.
Francesco Cipollone
Between 21:57 and 23:30 UTC on April 22, 2026, a malicious @bitwarden/cli@2026.4.0 was live on npm for 93 minutes — long enough to reach CI/CD pipelines, developer workstations, and cloud automation hosts. The payload steals credentials across GitHub, AWS, GCP, and Azure, propagates as a self-replicating npm worm, injects GitHub Actions workflow stealers, and poisons AI coding assistants by injecting an invisible manifesto into shell configuration files. This is the first documented npm supply chain attack executed through Trusted Publishing.
Francesco Cipollone
Phoenix Security launched Phoenix Blue at VulnCon 2026 — a standalone agentic vulnerability intelligence platform at phxintel.security. The platform indexes 300K+ CVE records and 2,080,512 advisory references from 15+ sources, adds six proprietary scoring systems, zero-day pre-CVE detection, and malicious package monitoring. Free for everyone, built agent-first with REST, GraphQL, and MCP integration.
Francesco Cipollone
Contents
Derek

Derek Fisher

Head of product security at a global fintech

Derek Fisher – Head of product security at a global fintech. Speaker, instructor, and author in application security.

Derek is an award winning author of a children’s book series in cybersecurity as well as the author of “The Application Security Handbook.” He is a university instructor at Temple University where he teaches software development security to undergraduate and graduate students. He is a speaker on topics in the cybersecurity space and has led teams, large and small, at organizations in the healthcare and financial industries. He has built and matured information security teams as well as implemented organizational information security strategies to reduce the organizations risk.

Derek got his start in the hardware engineering space where he learned about designing circuits and building assemblies for commercial and military applications. He later pursued a computer science degree in order to advance a career in software development. This is where Derek was introduced to cybersecurity and soon caught the bug. He found a mentor to help him grow in cybersecurity and then pursued a graduate degree in the subject.

Since then Derek has worked in the product security space as an architect and leader. He has led teams to deliver more secure software in organizations from multiple industries. His focus has been to raise the security awareness of the engineering organization while maintaining a practice of secure code development, delivery, and operations.

In his role, Jeevan handles a range of tasks, from architecting security solutions to collaborating with Engineering Leadership to address security vulnerabilities at scale and embed security into the fabric of the organization.

Jeevan Singh

Jeevan Singh

Founder of Manicode Security

Jeevan Singh is the Director of Security Engineering at Rippling, with a background spanning various Engineering and Security leadership roles over the course of his career. He’s dedicated to the integration of security practices into software development, working to create a security-aware culture within organizations and imparting security best practices to the team.
In his role, Jeevan handles a range of tasks, from architecting security solutions to collaborating with Engineering Leadership to address security vulnerabilities at scale and embed security into the fabric of the organization.

James

James Berthoty

Founder of Latio Tech

James Berthoty has over ten years of experience across product and security domains. He founded Latio Tech to help companies find the right security tools for their needs without vendor bias.

christophe

Christophe Parisel

Senior Cloud Security Architect

Senior Cloud Security Architect

Chris

Chris Romeo

Co-Founder
Security Journey

Chris Romeo is a leading voice and thinker in application security, threat modeling, and security champions and the CEO of Devici and General Partner at Kerr Ventures. Chris hosts the award-winning “Application Security Podcast,” “The Security Table,” and “The Threat Modeling Podcast” and is a highly rated industry speaker and trainer, featured at the RSA Conference, the AppSec Village @ DefCon, OWASP Global AppSec, ISC2 Security Congress, InfoSec World and All Day DevOps. Chris founded Security Journey, a security education company, leading to an exit in 2022. Chris was the Chief Security Advocate at Cisco, spreading security knowledge through education and champion programs. Chris has twenty-six years of security experience, holding positions across the gamut, including application security, security engineering, incident response, and various Executive roles. Chris holds the CISSP and CSSLP certifications.

jim

Jim Manico

Founder of Manicode Security

Jim Manico is the founder of Manicode Security, where he trains software developers on secure coding and security engineering. Jim is also the founder of Brakeman Security, Inc. and an investor/advisor for Signal Sciences. He is the author of Iron-Clad Java: Building Secure Web Applications (McGraw-Hill), a frequent speaker on secure software practices, and a member of the JavaOne Rockstar speaker community. Jim is also a volunteer for and former board member of the OWASP foundation.

Join our Mailing list!

Get all the latest news, exclusive deals, and feature updates.

The IKIGAI concept
x  Powerful Protection for WordPress, from Shield Security PRO
This Site Is Protected By
Shield Security PRO