· via dev.to (home feed)
Malicious PyPI and npm package incidents renew calls for hash-pinned installs and CLI sandboxing
A malicious LiteLLM package on PyPI and a trojanized Bitwarden CLI on npm show how quickly bad releases find victims; two dev.to posts map defenses from hash-pinned lockfiles to CLI sandboxing.

Two supply-chain incidents are circulating among developers this week: a malicious LiteLLM package on PyPI that stole credentials and planted a backdoor on install, and a trojanized Bitwarden CLI published to npm. Two dev.to posts walk through what happened and what teams can actually do about it.
Minutes of exposure, long cleanup
According to a dev.to post by Joel Díaz of Gap Hunter Labs, a malicious version of the Bitwarden CLI hit npm in April 2026 and stayed live for roughly ninety minutes — enough time to read SSH keys, .env files, and AWS, Azure and GCP credentials from anyone who installed it. In October, the repository behind the official OVHcloud CLI was briefly compromised the same way; the bad build was blocked after 94 minutes, but only once a customer noticed. Neither would be caught by signature-based antivirus, Díaz argues, because they were reputable tools pushing a single poisoned update rather than known-bad files.
A second, Vietnamese-language dev.to post describes a malicious LiteLLM version on PyPI, flagged on Hacker News, that installed credential stealers and a backdoor. The author's core point: writing pip install -U litellm in a Dockerfile, or leaving requirements.txt unpinned, hands anyone who compromises the maintainer's account code execution on your laptop, CI runners and production servers.
Code runs before you import
The PyPI post details three execution paths that fire earlier than many developers expect. A setup.py inside a source distribution runs at build time, before you have read any code. A .pth file in site-packages executes any line starting with import every time the Python interpreter starts, even for python -c "print(1)" — a persistence technique recent malware favors. Transitive dependencies can drag in a tainted version of a library you never installed directly.
Once running, the payload typically scans environment variables such as OPENAI_API_KEY and AWS_SECRET_ACCESS_KEY, reads ~/.aws/credentials, ~/.ssh/ and ~/.kube/config, and exfiltrates over HTTPS. CI runners are the richest targets, the post notes, because deploy secrets are already sitting there.
Lock, hash, and wait
Because malicious versions are usually detected and pulled from PyPI within hours to a few days, most victims are people who installed during that window. The post's two cheapest defenses are therefore strict pinning and deliberate delay: compile a lockfile with uv pip compile --generate-hashes, install with pip install --require-hashes --no-deps, and reject source distributions entirely via --only-binary=:all: so no setup.py ever executes.
A cooldown comes from uv's --exclude-newer flag, which accepts only packages published before a cutoff — the author suggests seven days, reasoning that researchers typically surface bad packages within 24 to 72 hours. Adding pip-audit to CI, failing builds on known advisories, closes the loop.
Audit and contain
For machines that may already be infected, the post shares a script that scans every .pth file in site-packages and flags import lines containing base64, exec, subprocess or network calls — unusually long lines are treated as compromised. Containment advice follows an assume-breach pattern: inject secrets only into deploy steps rather than job-wide environments, replace long-lived cloud keys with short-lived OIDC tokens, block network egress during builds with --network=none or an internal proxy such as devpi or Artifactory, and keep production keys out of shell profiles using per-project direnv. Maintainers, the post adds, should adopt PyPI Trusted Publishing and hardware-key 2FA.
If a bad version does slip through, the recommended order is quarantine the machine, rotate every credential that environment touched, rebuild the virtualenv from a verified lockfile, and review egress logs — deleting the package alone leaves the .pth backdoor in place.
A fence around untrusted CLIs
The same week's post by Díaz approaches the problem from the other side: sandbox the CLI itself. Every command you run — a package manager, a release binary, a teammate's script — executes as you, with full read access to your home directory. The author's tool, ghl-jail, is a Windows-only Python script needing no admin rights; it runs one command with access to a single project folder and nothing else, with network access off by default. Díaz is candid about limits: it sharply raises the cost of a mistake but will not stop an attacker actively targeting that sandbox.
Why it matters
Package installation is remote code execution by another name, and reputation-based scanning cannot catch a legitimate tool shipping one poisoned release. The npm incidents lived for roughly 90 minutes each and still found victims. Hash-pinned lockfiles, delayed upgrades, secret isolation and sandboxing are cheap, layered mitigations that assume something will eventually get through — because, as this week showed again, it does.
- #supply-chain
- #security
- #pypi
- #npm
- #python