This morning, SafeDep disclosed that LiteLLM 1.107.0 — published on PyPI today, October 21 — was backdoored. Not "had a vulnerability." Every one of its seven wheels installed a credential stealer and a remote-code-execution backdoor into site-packages, arranged so that both run every time any Python process starts on the host, including processes that never import litellm.
LiteLLM is the library a lot of teams use to route calls to LLM providers — which means its proxy databases are exactly where organizations keep their provider API keys. The stealer knew that: among its targets, per SafeDep's analysis, are SSH keys, cloud credentials (~/.aws, Azure, gcloud, kubeconfig), browser passwords and history, shell histories, CI/CD secrets, AI-tool configs (Claude Code, Cursor, Codex, and more), the environment of other processes via /proc/<pid>/environ, AWS instance metadata — and the LiteLLM_CredentialsTable itself. Collected data was encrypted and POSTed to a lookalike domain. A second payload, planted as sitecustomize.py, forked a detached daemon that re-ran the stealer hourly and downloaded fresh code to exec() from a server whose address it read from a GitHub file.
I did not install 1.107.0, and you shouldn't either — by the time I checked, there was nothing left to install. What I did instead is verify the current state of PyPI myself, check my own machine against the published indicators, and reproduce the mechanism with a harmless canary, because the mechanism is the part that generalizes to the next incident.
GET pypi.org/pypi/litellm/1.107.0/json → 404
GET pypi.org/pypi/litellm/1.106.2/json → 200, 8 files
GET pypi.org/pypi/litellm/1.107.0rc2/json → 200, 8 files
project "latest" version → 1.106.2
"1.107.0" in the project's release list → absent entirely
Details that line up with SafeDep's timeline (all times UTC, today):
1.107.0rc1 uploaded Oct 18 07:54 clean (per SafeDep)
1.107.0rc2 uploaded Oct 20 03:17 clean (per SafeDep)
1.106.2 uploaded Oct 21 10:44 7 wheels + sdist, none yanked
1.107.0 uploaded Oct 21 ~11:39 REMOVED — 404 everywhere
attacker's GitHub account (C2 pointer) deleted ~13:40
So the malicious release lived on PyPI for roughly two hours, and the registry's current state is consistent with a full removal rather than a yank: the version doesn't just have its files pulled, it's gone from the release index, and pip install litellm now resolves to 1.106.2. Two hours is a short window and a long one, depending on how many CI systems pin nothing and install at 12:00 UTC on a Wednesday.
How did it get in? SafeDep's forensic work — worth reading in full — found that the sdist's pyproject.toml gained one line, a maturin data = "cook" setting that copies a cook/ folder into the wheel's purelib root, i.e. straight into site-packages. The folder isn't in the sdist and isn't in any public commit. The wheels carry correct RECORD hashes and platform-consistent build fingerprints, which points at the project's own (private) release pipeline building from attacker-modified source, not at someone up hand-edited wheels with a stolen token. PyPI provenance attestations: none, for this or the neighboring clean releases.
The part I could test safely: why "runs in every Python process" is literally true. Python executes lines starting with import in .pth files in site-packages at interpreter startup, and imports sitecustomize at startup if it finds one. I built a throwaway venv with a benign cook.pth/ cook.py that just appends its PID to a file:
printf 'import cook\n' > site-packages/cook.pth
python -c "pass"
python -c "import sys; print('litellm' in sys.modules)"
litellm imported? False
--- canary marker file:
cook ran in pid 17899
cook ran in pid 17900
Two invocations, neither importing anything, both executed the planted module. That's the whole trick, and it's not exotic — .pth execution is a documented Python feature. The stealer needed no import hook, no sitecustomize race, nothing clever at runtime. The cleverness was all in getting three extra files through a real release pipeline.
One honest wrinkle from my own test: on this Ubuntu VM, my canary sitecustomize.py in the venv did not run, because /usr/lib/python3.12/sitecustomize.py sits earlier on sys.path and shadows it. On systems without a stdlib sitecustomize (stock python Docker images, macOS, Windows), the site-packages copy is the one Python finds. So the backdoor payload's reach varies by platform layout — but the .pth payload, the stealer, has no such dependency. It runs everywhere, unconditionally.
SafeDep published the indicators. The host-level checks are cheap:
site-packages contains cook.pth / cook.py / sitecustomize.py (planted)? NO
/tmp/.pc_once_72129118c59f5636c0bb (stealer already uploaded) NO
/tmp/remote_code_.lock (backdoor daemon ran) NO
PRIVCOLLECT_ACTIVE in environment NO
This VM never had LiteLLM installed, so a clean result was expected — the point of publishing the checklist is that it's a two-minute check for any machine that might have installed anything Python-flavored today. If you ran pip install litellm or built a fresh environment between roughly 11:39 and 13:40 UTC today, treat the host as compromised, not as "probably fine": the stealer's target list is specifically the secrets that live on developer and CI machines, and rotating the LLM keys alone doesn't cover SSH keys, cloud credentials, and browser passwords.
Strip the names off and the pattern is: one extra line in build config, three files at the root of site-packages, two Python startup mechanisms that have existed forever. Nothing about it required a zero-day. The defenses that would have caught it are equally unglamorous: a release-diff that asks "why does this wheel contain top-level modules that aren't in the repo," provenance attestations on uploads, and install-time auditing of .pth files — a file type whose entire legitimate user base is small and whose malicious potential is total.
LiteLLM will fix its pipeline. The next package's pipeline is the one to worry about. If your CI installs unpinned Python dependencies at build time, today's two-hour window was aimed at you.
Sources: SafeDep, "Compromised LiteLLM 1.107.0 on PyPI Installs a Credential Stealer and Backdoor," October 21, 2026 (safedep.io) — payload analysis, timeline, build forensics, and indicators of compromise are theirs. PyPI state, upload timestamps, host indicator checks, and the .pth/sitecustomize canary reproduction are my own, run this afternoon. I did not download or execute the malicious release.