Listen to this Post

Introduction:
The JavaScript ecosystem is under siege. On May 19, 2026, npm took the unprecedented step of invalidating every single granular write‑access token configured to bypass two‑factor authentication (2FA), after an automated burst from the “Mini Shai‑Hulud” supply chain worm published 639 malicious package versions across 323 unique packages in a single night. Worse still, this fourth‑generation worm doesn’t even need stolen tokens — it extracts OIDC credentials directly from GitHub Actions runner memory, walks straight past Trusted Publishing, and has already spread to over 170 npm and PyPI packages, including the 12‑million‑weekly‑download @tanstack/react‑router. This article breaks down exactly what happened, why your existing tokens are now worthless, and how to rebuild your CI/CD pipelines with defense‑in‑depth.
Learning Objectives:
- Harden CI/CD pipelines by migrating from long‑lived static tokens to OIDC‑based Trusted Publishing with MFA‑enforced staging gates.
- Detect and eradicate the Mini Shai‑Hulud worm using OSQuery, file hashes, and persistence‑hunt commands across Linux and Windows environments.
- Implement staged publishing to interpose human review before any package version reaches the live registry, breaking automated supply chain attacks.
You Should Know:
- Why Your Old npm Tokens Are Useless Now — And How to Generate Safe Replacements
On May 19, 2026, npm invalidated all granular access tokens that had write permissions and the “bypass 2FA” flag enabled. This is not optional. If your CI/CD pipelines, deployment scripts, or any automation relied on such tokens, they will now receive `E403` or `E401` errors when trying to publish. The attackers behind Mini Shai‑Hulud specifically targeted these bypass‑2FA tokens because they allow silent, non‑interactive publishing — exactly what a worm needs to spread undetected.
Step‑by‑step guide to recover your pipelines:
1. Generate new granular tokens (without bypass 2FA):
- Log into npmjs.com → Access Tokens → Generate New Token → Granular Access Token.
- Under 2FA Requirements, select “Require 2FA for write actions” — do not check “Bypass two‑factor authentication”.
- Assign the minimum permissions needed (e.g., `read and write` only for specific packages). Store the token securely in your secrets manager.
2. Update your CI/CD secrets:
Replace the old token value in your GitHub Actions secrets, GitLab CI variables, or Jenkins credentials with the newly generated token.
- Force a manual 2FA approval on your first publish (to verify the new token):
After updating your CI/CD, run a test publish manually. npm will prompt for a TOTP or WebAuthn challenge. Complete it once to “bless” the token for subsequent non‑interactive publishes.
Example GitHub Actions workflow snippet (using the new non‑bypass token):
- name: Publish to npm
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Note: With “Require 2FA” enabled, the first publish from a new IP or CI runner will need manual MFA. Subsequent publishes from the same runner may be allowed for a grace period — but this is a feature, not a bug, because it breaks automated worm propagation.
- The OIDC Token Extraction Exploit That Bypassed Trusted Publishing
The TanStack compromise on May 11, 2026, proved that even OIDC‑based Trusted Publishing is not a silver bullet. Attackers used a three‑step chain:
– Step 1: Abused a `pull_request_target` workflow trigger (the “Pwn Request” pattern) to execute code on a privileged runner.
– Step 2: Poisoned GitHub Actions caches to persist malicious code across runs.
– Step 3: Extracted the OIDC token directly from the runner’s process memory — not from stolen secrets — then used it to mint a valid npm publish token on the fly.
Because the OIDC token was legitimate (it came from GitHub’s own infrastructure), the resulting npm publish carried a valid SLSA Build Level 3 provenance attestation, meaning signature checks could not distinguish the malicious package from an authentic one.
Step‑by‑step guide to detect OIDC token extraction abuse in your environment:
On Linux / macOS (using `lsof` and process inspection):
Find any process that has open handles to the GitHub Actions OIDC token endpoint
sudo lsof -i :169.254.170.2 The IMDSv2 endpoint for OIDC tokens in Actions
Check for unexpected processes reading from /proc/self/environ (where OIDC tokens may be leaked)
sudo find /proc -name environ -exec grep -l "ACTIONS_ID_TOKEN_REQUEST_URL" {} \; 2>/dev/null
On Windows (PowerShell as Admin):
Check for processes that have network connections to the OIDC metadata endpoint
Get-NetTCPConnection -RemotePort 169.254.170.2 | Select-Object -Property OwningProcess, State
Get-Process -Id (Get-NetTCPConnection -RemotePort 169.254.170.2).OwningProcess | Select-Object ProcessName,Id
Search for environment variable leaks in running processes
Get-WmiObject Win32_Process | ForEach-Object { $_.CommandLine } | Select-String "ACTIONS_ID_TOKEN_REQUEST_URL"
Mitigation:
- Set `permissions:` blocks in GitHub Actions to the minimum required (e.g.,
contents: read, `id-token: write` only if absolutely needed). - Never use `pull_request_target` on workflows that also have `id-token: write` — separate sensitive workflows into dedicated environments.
- Enable npm’s new Staged Publishing (see section 3) so that even a successful OIDC token theft cannot push to live without manual MFA approval.
- Staged Publishing: The Human‑In‑The‑Loop Gate That Stops the Worm
On May 20, 2026 — one day after the token reset — npm officially rolled out Staged Publishing in public preview. This feature forces a mandatory human review step before any package version goes live. Even if an attacker compromises your CI/CD and obtains a valid OIDC token, they cannot push directly to the registry. Instead, the package lands in a staging area where a maintainer must explicitly approve it with 2FA via CLI or the npm website.
Step‑by‑step guide to enable Staged Publishing for your high‑impact packages:
Prerequisites:
- npm CLI version 11.15.0 or later (check with
npm -v). - Node.js version 22.14.0 or higher.
- 2FA enabled on your npm account (TOTP or WebAuthn).
Enabling staged publishing for a package that already exists on npm:
Navigate to your package root cd /path/to/your-package Stage a new version (this does NOT require 2FA — it only stages, not publishes) npm stage publish This will output a stage-id, e.g., "stg_abc123def456"
Reviewing and approving the staged package (requires 2FA):
Option A — CLI (fastest for trusted CI):
List all staged packages you have access to npm stage list Inspect the tarball contents before approval npm stage download stg_abc123def456 tar -tzf package-1.2.3.tgz verify no malicious files Approve the staged package (2FA will be prompted) npm stage approve stg_abc123def456
Option B — Web UI (more visual for code reviews):
– Go to npmjs.com → Staged Packages tab.
– Click on the staged version → Inspect → Approve (2FA challenge appears).
Integrating staged publishing into your CI/CD (example GitHub Actions snippet):
- name: Stage npm package
run: npm stage publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} token with write but requires 2FA for final approve
The actual approval must happen manually outside CI — that's the whole point.
Important: The approval step requires 2FA, meaning a human must authenticate. This breaks automated worms completely, because no malware can answer a TOTP prompt.
- How to Hunt for the Mini Shai‑Hulud Worm on Your Machines (Linux / Windows Commands)
The worm installs itself silently via a post‑install hook, daemonizes, and harvests credentials from cloud providers, CI/CD pipelines, and even AI coding assistants. It leaves behind specific indicators: files named router_init.js, setup.mjs, or transformers.pyz, and persistence hooks in `~/.claude/settings.json` and .vscode/tasks.json.
Step‑by‑step guide to detect and remove the worm:
On Linux / macOS (bash):
1. Hunt for the malicious JavaScript payloads sudo find / -name "router_init.js" -o -name "setup.mjs" -o -name "transformers.pyz" 2>/dev/null <ol> <li>Check for known malicious hash (ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c) sha256sum $(find / -name "router_init.js" 2>/dev/null) 2>/dev/null | grep "ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c"</p></li> <li><p>Look for persistence hooks in Claude Code and VS Code grep -r "masscan.cloud" ~/.claude/ ~/.vscode/ 2>/dev/null cat ~/.vscode/tasks.json 2>/dev/null | grep -i "postinstall|router_init"</p></li> <li><p>Check for the ominous "wipe" threat string grep -r "IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner" ~/node_modules/ 2>/dev/null</p></li> <li><p>Find processes that are daemonized and calling home to Session network sudo lsof -i | grep -E "getsession|masscan.cloud"
On Windows (PowerShell as Administrator):
1. Search all drives for malicious filenames
Get-ChildItem -Path C:\ -Filter router_init.js -Recurse -ErrorAction SilentlyContinue -Force
Get-ChildItem -Path C:\ -Filter setup.mjs -Recurse -ErrorAction SilentlyContinue -Force
<ol>
<li>Compute SHA256 hash of any found router_init.js and compare
$hash = Get-FileHash -Path "C:\path\to\router_init.js" -Algorithm SHA256
$hash.Hash -eq "ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c"</p></li>
<li><p>Check persistence in VS Code settings
Get-Content "$env:USERPROFILE.vscode\tasks.json" -ErrorAction SilentlyContinue | Select-String "postinstall|router_init"</p></li>
<li><p>Look for processes with outbound connections to Session nodes
Get-NetTCPConnection -State Established | Where-Object {$<em>.RemotePort -eq 443 -or $</em>.RemotePort -eq 80} | Select-Object RemoteAddress, OwningProcess | ForEach-Object {
$proc = Get-Process -Id $<em>.OwningProcess -ErrorAction SilentlyContinue
[bash]@{Process=$proc.ProcessName; PID=$proc.Id; RemoteIP=$</em>.RemoteAddress}
}
IOCs to block at the network level (add to your firewall / DNS sinkhole):
– Domains: filev2.getsession[.]org, api.masscan[.]cloud, `git-tanstack[.]com`
– IP address: `83[.]142[.]209[.]194`
5. Rotating Credentials Across Your Cloud and CI/CD Ecosystem
The Mini Shai‑Hulud worm does not stop at npm tokens. Once inside a developer’s machine, it systematically harvests AWS IAM keys, GitHub Personal Access Tokens, HashiCorp Vault tokens, Kubernetes secrets, and SSH keys, then uses them to lateral move across your entire infrastructure. npm’s token reset cuts off one vector, but if you suspect any exposure, rotate everything.
Step‑by‑step guide to credential rotation (Linux / CLI):
AWS: Invalidate old access keys and create new ones
aws iam list-access-keys --user-name your-username
aws iam delete-access-key --user-name your-username --access-key-id OLD_KEY_ID
aws iam create-access-key --user-name your-username store new key securely
GitHub: Revoke all personal access tokens (classic and fine-grained)
gh auth status
gh api /user/personal-access-tokens --paginate | jq '.[].id' | xargs -I {} gh api -X DELETE /user/personal-access-tokens/{}
HashiCorp Vault: Rotate tokens for all authenticated clients
vault token revoke -self revokes your own token
vault token create -policy=default -ttl=1h generate new token with short TTL
Kubernetes: Force re‑issuance of service account tokens
kubectl delete secret --all -n default be careful — this will break existing pods
kubectl rollout restart deployment --all
SSH: Regenerate host and user keys
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_new -N ""
Replace old authorized_keys entries with the new public key across all servers
For Windows environments (PowerShell):
AWS (using AWS Tools for PowerShell)
Remove-IAMAccessKey -UserName "your-username" -AccessKeyId "OLD_KEY_ID"
New-IAMAccessKey -UserName "your-username"
GitHub (via GitHub CLI for Windows)
gh auth status
gh api /user/personal-access-tokens --paginate | ConvertFrom-Json | ForEach-Object { gh api -X DELETE "/user/personal-access-tokens/$($_.id)" }
Pro tip: Use short‑lived tokens (e.g., OIDC + staged publishing for npm, OIDC for AWS, short‑TTL Vault tokens) as a defense‑in‑depth measure. A token that expires in one hour limits the worm’s window of opportunity even if it is stolen.
What Undercode Say:
- Key Takeaway 1: npm’s mass token reset is a necessary tourniquet, but it does not solve the underlying problem: worms can mint new tokens on the fly by extracting OIDC credentials from CI runner memory. Only staged publishing — which injects a human MFA check into the pipeline — breaks the automation loop that supply chain worms rely on.
- Key Takeaway 2: The Mini Shai‑Hulud campaign proves that provenance attestations (SLSA Level 3) provide false confidence when the credential issuer (GitHub Actions) itself can be compromised. Organizations must move beyond “verified signatures” and implement out‑of‑band human review for all package releases, combined with short‑lived, environment‑scoped secrets.
Analysis: The Mini Shai‑Hulud incident is not just another supply chain attack; it is a paradigm shift. For the first time, attackers demonstrated the ability to bypass both 2FA and Trusted Publishing without ever stealing a password or a token — they simply borrowed the pipeline’s own identity. This means that any CI/CD system that issues OIDC tokens is a potential mint for malicious packages, regardless of how well you protect static secrets. The only effective countermeasure is to assume that any automated pipeline can be compromised and to force a human MFA step before any release goes live. npm’s staged publishing is a good start, but it must be adopted across all ecosystems (PyPI, Maven, RubyGems) to truly raise the bar. Expect to see copycat attacks on GitHub Actions, GitLab CI, and Azure Pipelines in the coming months — and expect threat actors to adapt by targeting the human approval step itself (e.g., via social engineering or session hijacking).
Prediction:
Within the next 12 months, supply chain attacks will shift from stealing tokens to stealing OIDC‑authorized sessions from CI runners, making traditional secret rotation obsolete. The industry will respond by mandating air‑gapped signing keys and multi‑party release approval workflows for all critical packages. npm’s staged publishing is the first step toward a future where no package reaches the public registry without at least one human MFA verification — but the Mini Shai‑Hulud worm has already shown that even that may not be enough if the approver’s environment is compromised. Expect to see hardware‑based MFA (WebAuthn with biometrics) become mandatory for package maintainers, and zero‑trust CI/CD pipelines that never expose OIDC tokens to the runner’s memory space. The arms race has entered a new phase — and the attackers are currently winning.
▶️ Related Video (78% Match):
🎯Let’s Practice For Free:
IT/Security Reporter URL:
Reported By: Varshu25 Npm – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅


