Chronology of the 2026 Pipeline Hijackings
| Date |
Target / Campaign |
Core Mechanism |
Malware Family |
Key Indicator |
| Feb 28 |
Aqua Trivy & PyPI LiteLLM |
GitHub Actions privilege escalation |
Early Shai-Hulud & sysmon.py |
Canister traffic; typosquatted domains |
| Apr 22 |
@bitwarden/cli npm |
Poisoned GHA release workflow |
"Shai-Hulud: The Third Coming" |
Platform-detecting loaders |
| Apr 29 |
SAP npm & @cap-js |
npm token leaked via CircleCI pull request |
Shai-Hulud Core |
Outbound exfiltration to dead-drops |
| Apr 30 |
PyTorch Lightning (PyPI) |
Automated PyPI account hijacking |
Shai-Hulud Core |
Malicious releases v2.6.2 & v2.6.3 |
| May 11 |
TanStack, Mistral AI, Guardrails AI |
PR cache poisoning; GHA OIDC runtime memory theft |
Mini Shai-Hulud |
84 malicious npm packages |
| May 12 |
Open Source Leak |
Full source code leaked on BreachForums |
Mini Shai-Hulud |
Weaponized worm code publicly available |
| May 18 |
Nx Console (VS Code Extension) |
Contributor token abuse; orphan Git commits |
Mini Shai-Hulud |
~6,000 silent extension activations |
| May 19 |
@antv / atool Burst |
Compromised npm account; 637 malicious versions |
Mini Shai-Hulud |
22-minute automated publish storm |
| May 19 |
Microsoft DurableTask |
Stolen GitHub personal access token |
Mini Shai-Hulud |
Compromised Python SDK release cycle |
| Jun 1 |
@redhat-cloud-services |
Compromised employee GitHub account |
Miasma ("The Spreading Blight") |
32 compromised packages; cloud mappings |
Deconstructing the TanStack CI/CD Exploit
In the May 11 TanStack compromise attackers chained three distinct pipeline weaknesses to publish malicious packages bearing valid, cryptographically signed Level 3 SLSA (Software Artifacts Source Aligned) provenance.
- The Trigger Bypass: The attacker forked the public TanStack/router repository, naming it zblgg/configuration to evade fork-monitoring tools. They authored a malicious commit (65bf499d) using a fabricated identity <[email protected]> to mimic the official Anthropic Claude app, and prefixed the commit with [skip ci] to bypass push-event checks.
- The Trigger Exploitation: They opened pull request #7378, triggering TanStack's bundle-size.yml workflow. Because the workflow used the privileged pull_request_target trigger but explicitly checked out the untrusted fork's merge ref, the attacker's code executed directly within the security context of the base repository, gaining write access to secrets and tokens.
- Cache Poisoning: The malicious script (vite_setup.mjs) did not steal secrets immediately. Instead, it targeted the GitHub Actions build-cache system. Since cache writes use a runner-internal token that is completely unaffected by user-defined read-only permissions, the script modified the local pnpm store.
Memory Extraction & OIDC Abuse
On May 11, a legitimate release run pulled and restored the poisoned cache. When the build process initiated tanstack_runner.js, the payload extracted the short-lived OpenID Connect (OIDC) identity token directly from the process memory of the active GitHub Actions runner daemon (Runner.Worker) by reading /proc/<pid>/mem.
Using this OIDC token, the malware sent direct HTTP POST requests to registry.npmjs.org. Since publishing went through the official runner, Sigstore generated valid Level 3 SLSA provenance certificates. Over a six-minute window, the attackers successfully published 84 malicious versions across 42 @tanstack/* packages.
The Nx Console Extension Hijack
Using a GitHub personal access token stolen during the TanStack compromise, the attackers gained write access to the nrwl/nx monorepo.
- To avoid code-review pipelines, they pushed an orphan commit (a commit with no parent or connection to repository history) containing only a malicious package.json and index.js.
- They published Nx Console version 18.95.0 to the Visual Studio Marketplace, referencing the orphan commit via a hardcoded SHA.
- VS Code's silent auto-update pushed the extension to approximately 6,000 developer workstations.
June 2026: The Red Hat "Miasma" Wave
On June 1, 2026, the attackers targeted the @redhat-cloud-services npm namespace. An attacker compromised a Red Hat employee's GitHub account and pushed malicious orphan commits directly to two RedHatInsights repositories. The commits launched a minimal GitHub Actions workflow that requested an OIDC token and published 32 compromised packages.
The payload was identified as a descendant of the Mini Shai-Hulud worm dubbed Miasma. Crucially, Miasma added cloud control plane enumeration engine capabilities, scanning infected systems for active cloud CLI environments and querying GCP/Azure metadata endpoints to hijack broader cloud-hosted infrastructure.
To bypass network monitoring tools that flag traffic to known malicious domains, Miasma uses a highly resilient exfiltration loop. The malware programmatically generates public repositories directly on the victim's own hijacked GitHub accounts. These repositories are assigned distinct descriptions and host the RSA-encrypted exfiltration payloads. If direct token publishing fails, the worm falls back to posting double-Base64-encoded exfiltration payloads within commit messages carrying the signature "OhNoWhatsGoingOnWithGitHub:".
The VS Code Sandboxed Webview Zero-Day
In June 2026, computer scientist Ammar Askar disclosed an unpatched 1-click zero-day vulnerability in the VS Code sandboxed webview message-passing system on github.dev. It allows attackers to steal a user’s unscoped GitHub OAuth token, granting full access to all the victim's public and private repositories—simply by tricking them into clicking a link.
When a user works on github.dev, github.com POSTs an OAuth token to the web editor. Because this editor runs in the browser, sandboxed webviews (for Markdown or Jupyter previews) are isolated in <iframe> tags hosted on a separate origin (vscode-webview://...) to prevent malicious script execution. However, to keep keyboard shortcuts functional, webviews listen for keydown events inside the iframe and bubble them up to the main editor via a serialized did-keydown postMessage.
As the main window did not verify if these events were physically typed by a human, an untrusted script in a webview could programmatically synthesize keypresses.
The Exploit Path
To bypass security confirmation dialogs and achieve full execution, the exploit orchestrated a precise bypass sequence:
- Accepting Notifications: Programmatically dispatches Ctrl + Shift + A to auto-click the primary action on VS Code notifications.
- Abusing Trusted Workspaces: Places local recommended extensions inside .vscode/extensions (which run automatically on github.dev without publisher trust warnings).
- Bypassing Content Security Policy (CSP): The local extension's package.json registers custom keybindings. It maps Ctrl + F1 to execute workbench.extensions.installExtension with skipPublisherTrust: true.
- The Kill: When a user opens a repository containing a Jupyter notebook (.ipynb) with an HTML injection payload (such as <img src="data:foobar" onerror="payload();">), the payload simulates the keystroke chain, installs a hosted malicious extension, harvests the victim's unscoped GitHub OAuth token, and exfiltrates it.
- Workaround: Users can protect themselves by clearing cookies and local site data for github.dev in their browsers. This forces an explicit sign-in and warning prompt when an extension attempts to authorize with GitHub.
Incident Response Recommendations
If any of your developer systems, build environments, or CI/CD pipelines ran an npm install resolving to the compromised @redhat-cloud-services versions (June 1) or @tanstack versions (May 11), follow this exact order of operations to prevent system data destruction.
Neutralise the Dead Man's Switch
Do not rotate credentials immediately. If the background daemon detects token revocation, it will trigger a home directory wipe (rm -rf ~/*). Run the following commands to stop and disable the persistence mechanisms first:
# On Linux Systems: Stop and disable the malicious systemd services
systemctl --user stop gh-token-monitor.service kitty-monitor.service sysmon.service pgmon.service 2>/dev/null
systemctl --user disable gh-token-monitor.service kitty-monitor.service sysmon.service pgmon.service 2>/dev/null
# On macOS Systems: Unload the malicious Launch Agents
launchctl unload ~/Library/LaunchAgents/com.user.kitty-monitor.plist 2>/dev/null
launchctl unload ~/Library/LaunchAgents/com.user.gh-token-monitor.plist 2>/dev/null
rm -f ~/Library/LaunchAgents/com.user.*.plist
Step 2: Audit & Cleanse Workspaces
Ensure the worm has not planted persistent hooks in local development tools:
- Open and inspect ~/.claude/settings.json and .claude/settings.json for suspicious SessionStart hooks mapping to setup.mjs or router_runtime.js.
- Inspect .vscode/tasks.json for unauthorised folderOpen tasks.
- Audit your Git configuration and commit histories for unauthorised commits authored by the spoofed identity: claude <[email protected]>.
Step 3: Clean Package Directories
Wipe the compromised caches and dependencies directly from disk:
# Force clear local dependencies
rm -rf node_modules
rm -rf ~/.npm/_cacache
rm -rf ~/.local/share/pnpm/store
# Reinstall using known-clean versions in package.json
npm install --ignore-scripts
Step 4: Securely Rotate Credentials
Once local persistence is fully neutralised, rotate all potentially exposed secrets from a known-clean machine in this priority order:
- npm publish tokens and OIDC federation grants.
- GitHub Personal Access Tokens (PATs) and SSH private keys.
- Cloud provider credentials (AWS, GCP, Azure access keys and instance roles).
- HashiCorp Vault tokens and Kubernetes service account tokens.
Indicators of Compromise (IoCs)
| Artifact Type |
Indicator Value |
Context |
| Directory Path |
~/.local/share/kitty/cat.py |
Python-based C2 backdoor client |
| Systemd Service |
~/.config/systemd/user/kitty-monitor.service |
Linux background persistence daemon |
| LaunchAgent |
~/Library/LaunchAgents/com.user.kitty-monitor.plist |
macOS background persistence agent |
| User-Agent String |
google-api-nodejs-client/7.0.0 gl-node/20.11.0 gccl/7.0.0 |
User-Agent used by Miasma to scan GCP metadata |
| Repo Description |
"Miasma: The Spreading Blight" |
Explored/created public GitHub exfiltration repos |
| Repo Description |
"niagA oG eW ereH :duluH-iahS" |
Reversed string used for Shai-Hulud exfiltration repos |
| Git Branch Name |
codeql-static-analysis |
Malicious branch created to bypass audit logs |
| ICP Canister |
tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0.io |
C2 network command endpoint for Trivy campaign |
Mitigations and Recommendations
Hardening the CI/CD Pipeline
- Isolate External PRs: Never check out or run code from external forks inside privileged pull_request_target workflows. Build and test PRs strictly in the standard, unprivileged pull_request context.
- Enforce Privilege Isolation: Split tasks. Use an unprivileged pull_request job to run tests and upload passive data artifacts, then trigger a privileged workflow_run to download the artifacts and comment or publish.
- Scoped OIDC Bindings: Never bind an OIDC trust wildcard to an entire repository. Explicitly scope bindings to designated workflows on protected branches or tags.
- Audit Cache Scope: Treat the GitHub Actions build cache as an untrusted attack boundary. Do not generate cache keys from files that external contributors can easily modify.
Securing Local Developer Workstations
- Disable Run-Scripts: Enforce global package manager configurations to block automatic execution of package lifecycle scripts on install. Run package installations with the ignore flag: npm install --ignore-scripts
- Freeze the Lockfile: Enforce strict package manager lockfile checks in all automated builds to prevent runtime alterations:
- For Yarn: Use yarn install --frozen-lockfile
- Safe Incident Response: If a workstation is suspected of compromise, isolate and clone/image the physical drive before revoking active developer or GitHub API tokens. Revoking tokens prematurely will immediately trigger the malware's destructive home directory wipe, destroying critical forensic evidence.
Don’t forget to share this article