Lines of programming code displayed on a dark computer monitor
Photo via Unsplash

TL;DR: On April 30, 2026, attackers hijacked PyTorch Lightning’s official lightning package on PyPI and published two poisoned versions (2.6.2 and 2.6.3). The malware downloads the Bun JavaScript runtime, runs an 11 MB obfuscated credential stealer, and hoovers up SSH keys, GitHub tokens, npm tokens, AWS/Azure/GCP vault secrets, shell histories, and cryptocurrency wallets. It plants persistence hooks in VS Code and Claude Code so it re-executes every time you open your editor. Worst part: if it finds npm tokens with publish permissions, it injects itself into every package you maintain and republishes them, turning one compromised developer into a supply chain worm. The package sees 311,000+ downloads per day. Same “Shai-Hulud” threat actor behind the Bitwarden CLI attack two weeks earlier. PyPI quarantined the package within 42 minutes. If you imported lightning after April 30, rotate everything.

311,000 Downloads a Day. Two Poisoned Versions.

PyTorch Lightning is one of the most popular AI training frameworks in the Python ecosystem. The lightning package on PyPI pulls 311,000 downloads daily, 2 million weekly, nearly 8 million monthly [1]. It’s used by ML engineers, research labs, and companies running production AI pipelines.

On April 30, someone with access to PyPI credentials cloned the open source code, injected a malicious payload, and pushed two tampered builds directly to PyPI as versions 2.6.2 and 2.6.3 [2]. The legitimate package functions still worked. Your training runs would complete normally. But the moment Python executed import lightning, a daemon thread silently launched a credential stealer in the background with stdout and stderr suppressed [3].

The Lightning team detected and quarantined the malicious versions in 42 minutes [2]. That’s impressively fast. It also doesn’t matter if you were one of the developers who installed it during that window.

A JavaScript Stealer Hidden Inside a Python Package

The attack chain is clever and cross-platform in a way that security scanners didn’t anticipate.

Hidden inside the package was a _runtime directory containing two files. The first, setup.mjs, acts as a bootstrapper: it downloads Bun v1.3.13 (a JavaScript runtime) from GitHub if it’s not already on the machine [3]. The second, router_runtime.js, is a 14.8 MB obfuscated JavaScript payload that does the actual stealing.

The obfuscation isn’t casual. The payload uses javascript-obfuscator-style techniques with a secondary encryption layer: PBKDF2/SHA-256, 200,000 iterations, salt ctf-scramble-v2. Snyk identified this exact cipher signature in the earlier Bitwarden CLI compromise and Checkmarx KICS attacks, confirming shared tooling across all three incidents [3].

By using a JavaScript stealer inside a Python package, the attackers dodged Python-focused static analysis tools. Most PyPI scanners look for suspicious Python code. They don’t expect an npm-style attack hiding in a .mjs file.

80+ Credential File Paths. Every Cloud Vault. Your Crypto Wallet.

The stealer is comprehensive. Semgrep’s analysis found it sweeps 80+ credential file paths across the infected machine [4]:

  • GitHub tokens: OAuth tokens and Personal Access Tokens (regex: gh[op]_[A-Za-z0-9]{36,}), validated against api.github.com/user before exfiltration
  • npm tokens: Registry credentials (npm_[A-Za-z0-9]{36,}), also validated live
  • SSH keys: Your entire ~/.ssh directory
  • Shell histories: Bash and Zsh history files, which regularly contain pasted passwords, connection strings, and API keys
  • AWS credentials: IMDSv2 instance metadata, credentials files, Secrets Manager, SSM Parameter Store
  • Azure Key Vault: All accessible secrets
  • GCP Secret Manager: All accessible secrets
  • GitHub Actions runner secrets: Scraped directly from CI/CD runner memory
  • Cryptocurrency wallets: Local wallet files and seed storage
  • .env files: Every environment configuration in the project tree

The malware doesn’t just grab files. It validates tokens against live APIs before exfiltrating them, so the attacker gets confirmed-working credentials, not stale garbage [3].

It Lives in Your IDE

This is the part that separates Shai-Hulud from garden-variety supply chain malware. The payload doesn’t just steal and leave. It digs in.

Semgrep found the malware plants persistence hooks in two development tools [4]:

  • Claude Code: Injects .claude/settings.json with SessionStart hooks that re-execute the payload every time Claude Code launches
  • VS Code: Creates .vscode/tasks.json with folder-open triggers that fire the payload when you open a project

No user interaction required beyond opening your IDE. The malware reloads itself into the development environment on every session. And because it’s triggered by IDE settings files that live inside project directories, it can survive system restores that don’t touch workspace configs.

If you use Claude Code or VS Code and you imported the compromised version, check those files. Right now.

The Worm: One Developer Infects Every Package They Own

Here’s where this gets genuinely scary.

Unlike the Bitwarden attack, this variant has cross-ecosystem worm capabilities. If the malware finds npm credentials on the infected machine, it doesn’t just steal them. It injects the setup.mjs dropper and router_runtime.js payload into every npm package that token can publish to, bumps the version number, and republishes [4].

One compromised ML engineer who also maintains npm packages could silently poison the entire downstream dependency tree. PyPI to npm. Python to JavaScript. One ecosystem to another.

Socket’s researchers put it directly: “That makes this especially concerning because one compromised dependency can become a bridge into additional package ecosystems.” [1]

The Intercom team learned this the hard way. They traced their own compromise back to installing pyannote-audio, which pulled in lightning as a transitive dependency. They never installed the poisoned package directly. It came in through the dependency chain [1].

Four Exfiltration Channels Running in Parallel

The malware uses four simultaneous methods to get stolen data out [3][4]:

  1. HTTPS POST to attacker C2: Direct exfiltration to a command server
  2. GitHub commit-search dead drops: Encodes stolen tokens as base64 in commit messages, retrievable via GitHub’s public search API
  3. Public GitHub repositories: Creates repos with Dune-themed names on the victim’s account (look for descriptions containing “A Mini Shai-Hulud has Appeared”)
  4. Direct pushes to victims’ repositories: If GitHub tokens have write access, the malware commits stolen data directly to existing repos under a spoofed identity ([email protected])

Redundancy is the point. Even if you block one channel, three others are running.

The Shai-Hulud Campaign Keeps Evolving

The “Shai-Hulud” branding connects this attack to a growing chain. In chronological order:

  • Wave 1 (early 2026): Initial npm supply chain probes, basic credential theft
  • Wave 2 (April 22): Bitwarden CLI compromise: added AI tool targeting, cloud vault harvesting, GitHub dead drops
  • Wave 3 (April 30): PyTorch Lightning: added cross-ecosystem worm propagation (PyPI→npm), IDE persistence hooks, four parallel exfiltration channels

Each wave gets more dangerous. The threat actor, tracked as “TeamPCP,” had their social media accounts suspended but launched a dark web onion site to continue operations [1]. They’ve claimed a partnership with LAPSUS$ and named their encryption toolkit “CipherForce” [1].

The infrastructure is shared. The cipher signature, C2 patterns, and Dune-themed naming conventions are identical across Bitwarden CLI, Checkmarx KICS, and now PyTorch Lightning [3]. This isn’t copycats. It’s one team iterating fast.

What to Do Right Now

  • Check if you installed lightning 2.6.2 or 2.6.3. Run pip show lightning. If you see either version, assume full compromise. Downgrade immediately to 2.6.1: pip install lightning==2.6.1
  • Check transitive dependencies. You may have pulled in lightning through another package (like pyannote-audio). Run pip list | grep lightning across all environments
  • Rotate every credential on the machine. SSH keys, GitHub PATs, npm tokens, AWS/Azure/GCP credentials, API keys in .env files. All of them. The malware validates tokens live. If you had them, the attacker confirmed they work
  • Check your IDE configs. Look for unexpected entries in .claude/settings.json (SessionStart hooks) and .vscode/tasks.json (folder-open triggers). Delete anything you didn’t put there
  • Audit your GitHub repos. Search for repositories you didn’t create, especially with Dune-themed names or “Shai-Hulud” in the description. Check recent commits for author claude <[email protected]>
  • Check your npm publish history. If you maintain npm packages and had tokens on the infected machine, verify no unauthorized versions were published. The worm republishes your packages with the payload injected
  • Run snyk test to detect advisory SNYK-PYTHON-LIGHTNING-16323121

The AI Infrastructure Is Under Attack

In the last two weeks of April 2026, the same threat actor compromised a password manager’s CLI and one of the most popular AI training frameworks in the world. Both times, the malware specifically targeted developer tooling: AI coding assistants, cloud vaults, CI/CD runners.

The Shai-Hulud campaign isn’t after your Facebook password. It’s after the keys to production infrastructure. And it’s evolving faster than most security teams can respond.

PyTorch Lightning’s team caught this in 42 minutes. The Bitwarden team caught theirs in 90 minutes. Both are impressively fast response times. But with 311,000 daily downloads, even 42 minutes is enough to create a cascade of compromised developer machines that each become new infection vectors.

The structural fix isn’t faster response times. It’s Trusted Publisher controls, OIDC-bound publishing tokens, and mandatory approval gates for registry uploads [3]. Until those become standard, every pip install and npm install is a roll of the dice.

References

  1. The Hacker News: "PyTorch Lightning Compromised in PyPI Supply Chain Attack to Steal Credentials" (April 2026)
  2. Lightning AI: "How the PyTorch Lightning Community Discovered a Supply Chain Attack and Fixed it in 42 Minutes"
  3. Snyk: "Lightning PyPI Compromise: Bun-Based Stealer"
  4. Semgrep: "Shai-Hulud Themed Malware Found in the PyTorch Lightning AI Training Library"
  5. Socket: "lightning PyPI Package Compromised in Supply Chain Attack"
  6. Penligent: "PyTorch Lightning Supply Chain Attack Analysis"