Developer platforms, tools and supply chain
LiteLLM: October 2026
LiteLLM 1.107.0 Supply-Chain Compromise
On 21 October 2026 a malicious release of litellm, version 1.107.0, was published to PyPI (all seven wheels, plus an sdist with a tampered pyproject.toml) and to the project's Docker images (tags v1.107.0, latest, main-latest, main-stable), after attacker-controlled GitHub accounts triggered a release. This compromise has no CVE. The release has been quarantined on PyPI and the images removed. The last clean release is 1.106.2.
Each wheel drops three files into the root of site-packages, beside litellm/ rather than inside it: cook.pth (one line, import cook), cook.py (a credential stealer that calls itself privcollect), and sitecustomize.py (an hourly backdoor that fetches and runs attacker code from a GitHub dead drop). Python runs .pth files and sitecustomize.py at interpreter startup, so the malware runs on every Python start on the host, even if litellm is never imported. The stealer targets cloud tokens, developer and private keys, AI-tool credentials, browser data, environment variables, and a LiteLLM proxy's saved credentials, and exfiltrates to litellm[.]dev.
There is no safe in-place "clean." If 1.107.0 was installed from a wheel, or a LiteLLM container pulled on 21 October ran, treat the host as fully compromised: the stealer already ran. From a clean machine, revoke and rotate every credential the host could reach, rebuild it, and reinstall litellm pinned to 1.106.2 by digest. This script finds the compromise, hunts the indicators, and can contain the auto-executing backdoor so it stops running while you rebuild. Containment is not remediation.
LiteLLM quick start
-
Download the script. The repository is mirrored on GitHub and Codeberg; pick a base URL.
# BASE from GitHub: https://raw.githubusercontent.com/PrivacySafe/security-patches/refs/heads/main # BASE from Codeberg: https://codeberg.org/PrivacySafe/security-patches/raw/branch/main # curl -fLO "$BASE/litellm/litellm-oct2026-check.sh" curl -fLO https://raw.githubusercontent.com/PrivacySafe/security-patches/refs/heads/main/litellm/litellm-oct2026-check.sh -
Read it before running it, then make it executable.
less litellm-oct2026-check.sh chmod +x litellm-oct2026-check.sh -
See whether the compromise is present.
sudo ./litellm-oct2026-check.sh check -
Hunt the indicators (files,
/tmpmarkers, network traces in logs).sudo ./litellm-oct2026-check.sh hunt -
If found, contain the backdoor while you plan the rebuild and credential rotation.
sudo ./litellm-oct2026-check.sh quarantine
LiteLLM commands
| Command | What it does |
|---|---|
check (default) |
Finds litellm in every Python environment (and running containers) and flags 1.107.0, and reports the dropped malware files (cook.pth, cook.py, a malicious sitecustomize.py) in site-packages and the /tmp runtime markers. Read-only. Exits 0 if nothing found, 1 if compromise indicators are present, 2 if something couldn't be read |
hunt |
Read-only, deeper: the malware files across every site-packages, the /tmp markers (.pc_once_*, remote_code_loader.lock), and logs for the network indicators (litellm.dev, the GitHub dead drop). Exits 0 if clean, 1 if it found something |
quarantine |
Containment. Backs up (for forensics) and removes cook.pth and cook.py, and sitecustomize.py only when it carries the malware markers, so they stop running at Python start. Needs write access. The host is still compromised: rebuild and rotate credentials |
version |
Prints the script version. Every command prints it on its first line too |
LiteLLM what it looks at
- Python environments. The site-packages directories the active
python3reports, plus everysite-packagesfound under the scanned paths (system, user, venvs, pipx, conda). For each it reads the installedlitellmversion and flags 1.107.0. - Dropped files.
cook.pth,cook.py, andsitecustomize.pyin the root of each site-packages. A legitimatesitecustomize.pyexists in some environments, so it is only treated as malware when it carries the backdoor markers.cook.pthandcook.pyare the attacker's own file names. - Runtime markers. The
/tmp/.pc_once_*upload marker and the/tmp/remote_code_loader.lockthe backdoor daemon holds. - Containers. Running Docker or Podman containers whose
litellmis 1.107.0 or that carrycook.pth. A container is fixed by rebuilding on a clean 1.106.2 digest, not by a restart.
Before you run it
- Treat the host as fully compromised. This is the important one. The stealer runs on every Python start, so by the time you read this it has run. From a clean machine, revoke and rotate every credential the host could reach: cloud keys, API tokens, SSH and signing keys, browser sessions, and the LiteLLM proxy's own keys and model configuration.
quarantineis containment, not remediation. Removing the files stops the backdoor re-running. It does not undo the theft or guarantee the host is clean. Rebuild the host and reinstalllitellmpinned to 1.106.2 by digest.- Only the malware files are touched.
quarantineremovescook.pthandcook.py, and asitecustomize.pyonly if it carries the markers, so a legitimatesitecustomize.pyis left alone. Forensic copies go to the backup directory. - Containers carry their own copy. Rebuild any image that pulled 1.107.0 (or the
latest/main-*tags on 21 October) on a clean 1.106.2 digest. - GNU/Linux only , and it finds installs under the scanned paths. Point
SCAN_PATHSat an environment kept elsewhere. - A path it could not read is not a clean result. If a scan path exists but cannot be read,
checkexits2(when nothing else is found) instead of0. A path that does not exist is skipped. Directories inside a readable path that you cannot read are skipped, so run it as root for full coverage. - It also checks running docker and podman containers, unless you name a directory or set
SCAN_CONTAINERS=0. A read-only probe in each container finds thelitellmmetadata directories (and thefastapianduvicornones beside them), proxy configuration files, lock and requirements files that mention litellm, and image tags in compose-style files. It copies only what the check reads into a private temporary folder: a one-line marker for each proxy config (the keys stay in the container), the matchedberriai/litellm:TAGstrings from compose, Helm and.envfiles, and requirements lines with index URLs and credentials dropped. The script then runs once per container in isolation, so one container's proxy config never makes another container's copy look exposed./app, where the official image keeps its configuration, is searched in containers. A path shown as.../docker_NAME/PATHis the PATH inside the container NAME.
LiteLLM proxy admin escalation (CVE-2026-114612)
Script: litellm/litellm-escalation-check.sh
This is a different problem from the malicious 1.107.0 release above: a genuine vulnerability in genuine releases. The LiteLLM proxy uses one cryptographic context for two purposes, sealing secrets at rest and minting session tokens. An authenticated user with internal_user privileges can request a new API key with a crafted metadata field that holds a forged administrator credential as the "secret". The proxy encrypts it and returns it, and the user replays it as a bearer token to become proxy_admin, which reaches arbitrary commands through the MCP stdio endpoint.
| CVE | CVE-2026-114612 (CWE-269, CWE-345, CWE-441, advisory GHSA-7hp6-4w63-5g45, published 22 October 2026) |
| Severity | Critical, CVSS 3.1 9.9 (an authenticated, low-privilege user) |
| Affected | 1.87.0 up to 1.100.4, 1.101.0 up to 1.101.3, 1.102.0 up to 1.102.2, 1.103.0 up to 1.103.1, and 1.104.0-rc.1 up to 1.104.0-rc.2 |
| Fixed | 1.100.4, 1.101.3, 1.102.2, 1.103.1 and 1.104.0-rc.2 (all on PyPI), and every later release. move 1.87.0 through 1.99.x to 1.100.4 or newer |
| Note | The vendor advisory lists 1.91.0 as the first exploitable version. A third-party reading says 1.87.0 to 1.90.x also need EXPERIMENTAL_UI_LOGIN. The tool treats the whole CVE range as affected |
| Needs | The proxy. Using litellm only as a Python library (the SDK), with no proxy running, is not exposed. The tool reports which it found evidence of |
Do not confuse the two. The last clean release before the malicious one is 1.106.2, which is above every fixed version here. If the new script meets 1.107.0 it says so and points to litellm-oct2026-check.sh.
Quick start
curl -fLO https://raw.githubusercontent.com/PrivacySafe/security-patches/refs/heads/main/litellm/litellm-escalation-check.sh
less litellm-escalation-check.sh
chmod +x litellm-escalation-check.sh
./litellm-escalation-check.sh check
By default it searches /usr/lib /usr/local/lib /opt /srv /var/lib /etc /home /root. Pass directories to narrow it. Exit 0 nothing exposed, 1 an affected proxy, a floating image tag or the malicious 1.107.0, 2 bad arguments. It is read-only.
How it decides
- Installed copies (
litellm-*.dist-info), pins (requirements*.txt,poetry.lock,uv.lock,pdm.lock,Pipfile.lock) and container image tags in compose, Helm, Kubernetes and Dockerfiles (berriai/litellmandberriai/litellm-database). - Proxy evidence:
fastapianduvicorninstalled beside litellm, alitellm[proxy]extra or those packages in the same pin file, a LiteLLM proxy configuration file (model_listorgeneral_settings), or any container image (the images are the proxy). An affected version with evidence is exposed. Without it the tool warns and exits0, because SDK-only use is not exposed. - Per release line: a version on one line can be affected while a lower one on another line is fixed (1.100.4 is fixed, but 1.101.0 to 1.101.2 are affected), so each line has its own first fixed release.
1.104.0rc1is affected and1.104.0rc2and the final1.104.0are fixed. - Floating tags such as
main-latestormain-stabledo not say which release is running, so the tool says it cannot tell and exits1. It does not open running containers. - Look-alikes such as
litellm_proxy_extrasandlitellm_enterpriseare different packages and are not matched, including when listed first in a lock file.
Fixing it
Upgrade to 1.100.4, 1.101.3, 1.102.2, 1.103.1 or 1.104.0-rc.2 or newer, on the line you run. Never install 1.107.0. After upgrading, check the proxy's user list for administrators you did not create (PrivacySafe recommendation).
Sources
The Security Patches software and this documentation are dedicated to the public domain under CC0 1.0 Universal. Other pages on privacysafe.app/docs are CC BY-SA 4.0 unless the page says otherwise.