Listen to this Post

Introduction:
A sophisticated supply-chain compromise has rocked the JavaScript ecosystem. Malicious actors successfully published 84 malicious npm package artifacts across 42 packages within the popular TanStack namespace, marking a significant escalation in the ongoing “Mini Shai-Hulud” campaign. This attack, which targeted developer CI/CD pipelines, exploited weaknesses in GitHub Actions to inject credential-stealing malware, potentially affecting millions of weekly downloads across the global npm ecosystem.
Learning Objectives:
- Understand the technical chain of vulnerabilities that lead to a successful OIDC token hijacking and the injection of malicious code into a trusted build pipeline.
- Identify indicators of compromise (IOCs) and learn to scan projects for malicious dependencies, obfuscated payloads, and permission escalations.
- Implement emergency response and long-term hardening strategies, including credential rotation, cache purging, and CI/CD configuration reviews to mitigate and prevent similar attacks.
You Should Know:
- The Anatomy of a Sophisticated CI/CD Chain Reaction
The TanStack compromise was not a simple credential theft but a masterclass in exploiting modern development workflows. The attack leveraged a chain of three distinct weaknesses within GitHub Actions to publish malicious packages using the project’s own trusted identity, bypassing traditional security controls.
Step‑by‑step guide explaining what this does and how to use it:
This guide details the attack flow, allowing defenders to trace the steps of the TanStack compromise:
- Reconnaissance and Cache Poisoning: The attacker initially forked the legitimate `TanStack/router` repository, renaming it (e.g., to
zblgg/configuration) to evade basic fork-list searches. They then opened a Pull Request (PR) against the legitimate repository. - Exploiting
pull_request_target: This PR triggered a `pull_request_target` workflow. This specific type of GitHub Action workflow is designed to run in the context of the target (base) repository and has access to base secrets, even when triggered by a PR from a fork. - Malicious Code Execution: The attacker’s PR workflow was configured to check out and execute code from their malicious fork. This code’s purpose was to poison the GitHub Actions cache, specifically the `pnpm` store, with malicious binaries.
- Hijacking a Legitimate Release: When a legitimate maintainer later merged a different PR to the main branch, the automated release workflow executed. During the build process, it restored the previously poisoned pnpm cache, inadvertently executing the attacker-controlled binaries.
- OIDC Token Extraction: These attacker-controlled binaries, running within the trusted context of the release pipeline, accessed the GitHub Actions runner’s process memory (e.g.,
/proc/<pid>/mem) to extract the OpenID Connect (OIDC) token. This token is a short-lived credential issued by GitHub to the runner to authenticate with other services. - Publishing Malicious Packages: Using the stolen OIDC token, the attacker impersonated the TanStack release pipeline and published 84 malicious versions to the npm registry between 19:20 and 19:26 UTC. Notably, these packages carried valid SLSA Build Level 3 provenance attestations, making them appear legitimate to automated verification systems.
Detection and Forensics Commands:
To detect if your environment was affected, you must audit your lockfiles and CI logs:
On Linux/macOS (in your project root) Check for the malicious optionalDependencies entry in your lockfile grep -A 2 "optionalDependencies" package-lock.json yarn.lock pnpm-lock.yaml 2>/dev/null | grep "@tanstack/setup" Search for the specific GitHub commit hash grep -r "79ac49eedf774dd4b0cfa308722bc463cfe5885c" . On Windows (PowerShell) Select-String -Path "package-lock.json","yarn.lock","pnpm-lock.yaml" -Pattern "@tanstack/setup" Audit your GitHub Actions logs via GitHub CLI gh run list --limit 100 --json databaseId,displayTitle,status,conclusion,createdAt | jq '.[] | select(.createdAt > "2026-05-11T19:20:00Z")'
2. The “Mini Shai-Hulud” Worm: A Credential-Stealing Powerhouse
The payload delivered by this attack is a 2.3 MB, heavily obfuscated JavaScript file (router_init.js). It acts as a self-propagating worm designed for maximum damage within a developer’s environment. Its design showcases a level of sophistication that elevates it beyond simple malware. Deobfuscating and analyzing this file requires advanced reverse-engineering skills, but understanding its core functions is critical for defenders.
Step‑by‑step guide explaining what this does and how to use it:
This guide explains how to simulate the worm’s behavior in a controlled sandbox environment for analysis and education. Do not run this on any production or sensitive system.
- Credential Harvesting: The worm’s primary function is to scan the compromised host for sensitive data. It targets a wide range of locations and systems, including environment variables, local files, and metadata services.
– File System Search: It searches through common configuration and credential file paths. In a sandbox, you could emulate this search with find:
Simulate the worm's file search on a test directory This command does NOT exfiltrate, only shows what it would find find ~ -type f ( -name ".npmrc" -o -name ".env" -o -name ".pem" -o -name "id_rsa" -o -name ".git-credentials" ) 2>/dev/null
– Cloud Metadata APIs: The malware queries internal APIs like AWS IMDSv2 (http://169.254.169.254/latest/meta-data/iam/security-credentials/`), GCP metadata, and Kubernetes service account token files (/var/run/secrets/kubernetes.io/serviceaccount/token).filev2.getsession.org
2. Exfiltration Over Redundant Channels: To ensure the stolen data reaches the attacker, the worm uses a triple-redundant C2 architecture, employing three distinct channels:
1. Session Messenger Network: Data is encrypted and exfiltrated using the Session/Oxen network (), which provides end-to-end encryption and is difficult to block.git-tanstack[.]com
2. Typosquat Domain: A fallback channel using a plain HTTP POST to, a domain designed to impersonate a legitimate service.registry.npmjs.org/-/v1/search?text=maintainer:
3. GitHub API Dead Drops: The worm uses stolen GitHub tokens to create public or private repositories and commit the stolen data as files, disguised as legitimate commits.
3. Self-Spreading Mechanism: This is the worm's most dangerous feature. After stealing credentials, it enumerates all packages the victim maintainer has on npm () and attempts to republish them with the malicious injection, using the newly stolen tokens.rm -rf ~/`, destroying the user’s home directory.
4. Persistence and Destructive Capability: On developer machines, the malware installs a background daemon called `gh-token-monitor` (via LaunchAgent on macOS or systemd on Linux). This daemon checks the validity of GitHub tokens every 60 seconds. If a token has been revoked, it attempts to execute
3. Emergency Response: Containment, Remediation, and Credential Rotation
If you or your CI/CD pipeline installed any of the affected packages between approximately 19:20 and 19:30 UTC on May 11, 2026, you must assume the installation host is fully compromised and act immediately.
Step‑by‑step guide explaining what this does and how to use it:
Follow this strict order of operations to contain the breach and prevent the malware from stealing newly generated credentials:
1. Containment (Do NOT Rotate Credentials Yet):
- Isolate the Host: Immediately disconnect the affected machine or CI runner from the network to prevent further data exfiltration.
- Privatize Malicious Repos: If the worm created a suspicious public repository (often named randomly with the description “Sha1-Hulud: The Second Coming”), do not delete it. Immediately change its visibility to Private. This stops the attacker from accessing the exfiltrated data you will need for forensics.
Using GitHub CLI, list recently created repositories gh repo list --limit 50 --json name,description,createdAt,visibility \ --jq '.[] | select(.createdAt > "2026-05-11T19:00:00Z")' If you find a suspicious repo, set it to private gh repo edit <REPO_NAME> --visibility private
- Disable Malicious CI Components:
Check GitHub Actions for "SHA1HULUD" runners gh api -X GET /repos/:owner/:repo/actions/runners --jq '.runners[] | select(.name | contains("SHA1HULUD"))' List and disable any suspicious workflows gh workflow list --all
2. Malware Removal:
- Purge the npm cache and remove all installed dependencies from the project to ensure complete cleanup.
In the affected project directory npm cache clean --force rm -rf node_modules On Linux/macOS, also check for the persistent daemon sudo systemctl stop gh-token-monitor sudo systemctl disable gh-token-monitor On macOS, check for LaunchAgent launchctl list | grep gh-token-monitor
- For CI runners, the safest and most reliable remediation is to decommission the existing runner and provision a brand-new, clean one.
3. Credential Rotation (Now Do This):
- Rotate ALL secrets that were accessible from the compromised host. This includes but is not limited to:
- AWS, GCP, Azure access keys and secrets
- GitHub Personal Access Tokens (PATs) and `GITHUB_TOKEN` secrets
- npm tokens and `.npmrc` credentials
- Kubernetes service account tokens, HashiCorp Vault tokens
- SSH private keys stored on the host
- After rotating secrets, reinstall dependencies from a clean lockfile.
After purging cache and node_modules npm install --package-lock-only npm ci
4. Hardening CI/CD Pipelines Against Token Theft
The TanStack incident highlights a fundamental flaw in long-lived secrets and over-permissive OIDC tokens. The goal is to eliminate static credentials and adopt a “zero-trust standing privileges” model for your automation pipelines. This approach ensures that even if a CI/CD environment is breached, the attacker’s window of opportunity and scope of access are drastically limited.
Step‑by‑step guide explaining what this does and how to use it:
- Eliminate Long-Lived npm Tokens: The attacker in this case stole an OIDC token, but many pipelines still rely on static `NPM_TOKEN` secrets. The most effective mitigation is to delete them entirely.
– Implement OIDC Trusted Publishers: Configure npm to trust your CI/CD provider (GitHub Actions, GitLab CI) directly. This allows your pipeline to exchange its OIDC token for a short-lived, single-use npm publish token, eliminating long-lived secrets.
– The official documentation states: “Stop Rotating npm Tokens. Delete Them. The only credential that can’t be stolen at rest is the one that doesn’t exist”.
2. Lock Down `pull_request_target` Workflows: This workflow type is a known attack vector because it provides elevated permissions for code from forks. It should be used with extreme caution.
Vulnerable Configuration
on:
pull_request_target:
types: [opened, synchronize]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
DANGER: This checks out the code from the FORK, not your base branch
ref: ${{ github.event.pull_request.head.sha }}
– Secure Alternative: Never check out the fork’s code directly in a `pull_request_target` workflow. If you must run code from a PR, do so in a separate, isolated workflow that has no access to secrets. Or, use a two-step process: the `pull_request_target` workflow only creates a temporary environment, and later, after a maintainer’s approval, a separate `issue_comment` or `workflow_run` job handles the sensitive operations.
3. Limit OIDC Token Permissions: OIDC tokens can be as dangerous as long-lived keys if they have excessive permissions. Always scope them down.
Example of scoping an OIDC token for a publishing job permissions: Grant the minimal set of permissions contents: read id-token: write Needed to request the OIDC token packages: write Needed to publish to GitHub Packages
– Adopt the principle of least privilege. A token used only for publishing a single package should not have write access to the entire repository or other packages.
4. Harden Build Caches: The attack used a poisoned pnpm cache. Use immutable, versioned cache keys and consider read-only caches for release builds.
Example of a locked-down cache key
- name: Cache pnpm store
uses: actions/cache@v4
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
Do NOT restore from a cache that could have been poisoned by a fork
What Undercode Say:
- Key Takeaway 1: Trust as a Vulnerability. The TanStack attack demonstrates a critical shift in the threat landscape. Attackers are no longer just hunting for zero-day exploits in code; they are meticulously crafting chains of weaknesses inherent to the trust models and automation convenience features of platforms like GitHub Actions and npm. Your CI/CD pipeline is now a prime target, not just a tool for deployment.
- Key Takeaway 2: The New Perimeter is Your CI/CD Environment. The combination of self-propagation, redundant C2 channels, and a destructive failsafe (
rm -rf ~/) shows an unprecedented level of operational maturity from threat actors. Defending against this requires a “shift-left” approach to security, extending rigorous vulnerability management and zero-trust principles to your entire automation and code review process.
Prediction:
The “Mini Shai-Hulud” campaign will serve as a watershed moment, forcing a paradigm shift in how open-source ecosystems and CI/CD platforms are secured. We will see an accelerated deprecation of long-lived publish tokens in favor of OIDC and workload identity federation as a mandatory security baseline. Furthermore, package registries (npm, PyPI, RubyGems) will be forced to implement real-time behavioral scanning of package installation scripts and binary artifacts, moving beyond simple static analysis. The era of implicit trust in a package based solely on its name or maintainer is over; automated, continuous verification will become the new standard.
▶️ Related Video (82% Match):
🎯Let’s Practice For Free:
IT/Security Reporter URL:
Reported By: Cybersecuritynews Share – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅


