LiteLLM 1.107.0 supply chain compromise: what to check, what to rotate and the 2026 CVEs
On 21 October a hijacked release pipeline pushed a credential stealer as LiteLLM 1.107.0 to PyPI and Docker. Here is how to tell if you ran it, what to rotate, the IOCs, and every LiteLLM CVE of 2026 in one table.
By the OpenWAF security team
In short. On 21 October 2026 an attacker hijacked LiteLLM’s release pipeline and published litellm 1.107.0 to PyPI and Docker with a credential stealer inside. It was live for about two hours. If you installed it, or pulled the latest, main-latest or main-stable images in that window, treat the host as compromised.
- Don’t start with
pip: remove the startup files first, then rebuild from scratch on a pinned version (1.106.2 or later 1.106.x). - If the host had internet access, assume the data left. Rotate every provider key in the LiteLLM database, the master and virtual keys, the database password and the cloud role.
- Separately, LiteLLM had a run of serious CVEs in 2026, from an unauthenticated SQL injection to admin takeover. The table below lists them, and every 1.106.x release is newer than all the affected versions.
- A WAF can’t catch malware inside your host. In front of an AI gateway it does block the Host-header bypass (CVE-2026-49468) and it limits what an exposed endpoint will accept.
What happened to LiteLLM 1.107.0
LiteLLM is a widely used open-source gateway that puts one OpenAI-style API in front of many model providers. It usually holds every provider key an organisation owns. That makes a backdoored release very valuable to an attacker.
The malicious release was not built from LiteLLM’s source. According to LiteLLM’s root-cause analysis, the attacker used stolen maintainer tokens to point the legitimate release pipeline at a lookalike fork. The official v1.107.0 tag on GitHub is clean, and the payload only exists in the built wheels and images. All times below are UTC on 21 October 2026.
| Time (UTC) | Event |
|---|---|
| 10:08 | Branch protection on the release repository is overridden with a stolen owner token. |
| 11:11 | The production gate is approved with a second stolen maintainer token. The build comes from the lookalike fork Berri-AI/litellm. |
| 11:39–11:40 | Seven malicious litellm==1.107.0 wheels appear on PyPI. |
| 11:46 | Docker Hub and GHCR images are pushed under the tags v1.107.0, latest, main-latest and main-stable. |
| 11:53–12:24 | The attacker deletes workflow runs and force-pushes the history clean. |
| 12:06 | A community member reports the malicious release on GitHub, less than half an hour after publication. |
| by 13:23 | PyPI quarantines 1.107.0. |
| by 13:51 | The GHCR tags are no longer available. |
| 14:20 | The Docker Hub tags are removed or repointed to clean images. |
LiteLLM says customers on its private enterprise registry were not affected. No source we read gives a download count for 1.107.0. The 92 million monthly downloads quoted in the press are for the project as a whole.
How the attacker got in
The root cause goes back months. On 27 May 2026 a configuration file committed to a public LiteLLM repository leaked the master key of an internal agent platform, and that key was never revoked. On 10 October the attacker used it to obtain a GitHub organisation owner’s CLI token. Throwaway CI workflows then sent two more maintainers’ tokens to an external webhook. LiteLLM had also recently relaxed release approval to allow any two engineers. With the three stolen tokens, the attacker overrode branch protection, approved the release and erased the traces. LiteLLM’s first post blamed a different path, and its later analysis corrected that, so rely on the attack-chain post.
What the malware does
JFrog and Microsoft analysed the payload:
- It runs without being imported. The wheel drops
cook.pth, which Python executes at every start, includingpipitself. That file loadscook.py, a stealer the authors call “privcollect”. - It steals almost everything it can read:
- environment variables of the current process and of every readable
/proc/*/environ; - cloud credentials and instance metadata (AWS, Azure, GCP), Kubernetes and Docker configuration;
- SSH, GPG and TLS keys, browser data, Git, package registry and AI tool tokens;
- the provider credentials in LiteLLM’s own database (
LiteLLM_CredentialsTableandLiteLLM_ProxyModelTable), reached throughDATABASE_URL.
- environment variables of the current process and of every readable
- It sends the data out encrypted (AES-256 plus RSA-4096) over plain HTTP to a lookalike domain.
- It installs a loader.
sitecustomize.pystarts an hourly loader on Linux and macOS that fetches code from an address published in a GitHub file. That file was empty when the researchers checked, and no second stage has been confirmed.
Am I affected?
You are at risk if any of these is true:
- you installed
litellm==1.107.0from PyPI between 11:39 and 13:23 UTC on 21 October, by hand, in CI, or through a dependency range that allowed it; - you pulled or started a LiteLLM image from Docker Hub or GHCR between 11:46 and 14:20 UTC under
v1.107.0,latest,main-latestormain-stable, including automatic pulls by a scheduler, autoscaler or deployment.
Check without starting Python in the suspect environment:
# files the wheel left in site-packages (no output is not proof of a clean host)
find / -path '*site-packages*' \( -name 'cook.pth' -o -name 'cook.py' -o -name 'sitecustomize.py' \
-o -name 'litellm-1.107.0.dist-info' \) 2>/dev/null
ls -la /tmp/remote_code_loader.lock /tmp/.pc_once_72129118c59f5636c0bb 2>/dev/null
# the image digest you are running
docker images --digests | grep -i litellm
The marker files only prove infection when present. Containers and /tmp cleanup remove them.
What to do now
- Don’t run
piporpythonin the affected environment first. Both start the stealer again. - Delete
cook.pth,cook.py,sitecustomize.py,__pycache__/cook*.pycandsitecustomize*.pycfrom every site-packages directory. Then kill the detached Python process that holds/tmp/remote_code_loader.lock. - Rebuild virtual environments and images from scratch rather than cleaning them in place. Pin an exact version (LiteLLM’s advice was 1.106.2; 1.106.3 and 1.106.4 have since been published).
- If the host had outbound internet access, assume the data was sent. Rotate:
- every provider key stored in the LiteLLM proxy database;
- the LiteLLM master key and all virtual keys;
- the
DATABASE_URLpassword; - the instance or task IAM role and any cloud keys;
- every secret in the environment of any process on that host;
- SSH, GPG, Git and package registry tokens.
- In AWS, look in CloudTrail for
GetCallerIdentitycalls from the instance role around the install time, then for use of that role from outside your network. Do the same in your providers’ usage dashboards. - Block the indicators below at your egress proxy or DNS resolver, and search past logs for them.
Indicators of compromise
These come from LiteLLM, JFrog and Microsoft. Domains are defanged.
| Type | Indicator |
|---|---|
| Exfiltration | hxxp://www.litellm[.]dev/healthcheck, header X-Token: XWiA8gZNa7NcX2XRoAEb |
| Loader dead drop | raw.githubusercontent[.]com/letters9813/pythonclient-test/main/domain.txt, then hxxp://{domain}/codepy |
| Files | cook.pth, cook.py, sitecustomize.py in site-packages; litellm-1.107.0.dist-info; /tmp/remote_code_loader.lock; /tmp/.pc_once_72129118c59f5636c0bb; /tmp/.pc_sq_*; /tmp/.pc_e_* |
| Environment | PRIVCOLLECT_ACTIVE |
| Image index | sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339e (berriai/litellm) |
| Attacker infrastructure | IP addresses 69.48.229.143 and 199.91.221.39, lookalike GitHub organisation Berri-AI, commit 20535d8f |
Microsoft also publishes SHA-256 hashes of the startup files and Defender detection names (Trojan:PyPI/LiteLlmSupplyChain) in its write-up.
Harden the next upgrade
- Install Python dependencies from a lock file with hashes (
pip install --require-hashes -r requirements.txt, or uv or Poetry lock files). A new upload under an old version then fails instead of installing. - Deploy images by digest (
berriai/litellm@sha256:…), never bylatestormain-*. Let a person or a bot open the upgrade, and wait a day before taking new releases of critical components. - Give the gateway’s host as little as possible: no broad cloud role, no SSH keys, no unrelated secrets in its environment, and outbound traffic limited to the model providers it needs.
LiteLLM CVEs of 2026
The supply chain attack came after a year of serious bugs in the LiteLLM proxy itself. This table collects them from the GitHub advisories and CVE records. CVSS is the highest score given in the record. Every 1.106.x release is newer than all the affected versions listed.
| CVE | Affected | Fixed in | Impact |
|---|---|---|---|
| CVE-2026-42208 | 1.81.16 to < 1.83.7 | 1.83.7 | SQL injection in API key verification, without authentication. CVSS 9.8. |
| CVE-2026-42271 | 1.74.2 to < 1.83.7 | 1.83.7 | Command execution through the MCP stdio test endpoints, for an authenticated user. CVSS 8.8. |
| CVE-2026-47102 | < 1.83.10 | 1.83.10 | A user can change their own role to proxy_admin through /user/update. CVSS 8.8. |
| CVE-2026-47101 | < 1.83.14 | 1.83.14 | An internal user can create keys whose allowed_routes exceed their role and reach proxy_admin. CVSS 8.8. |
| CVE-2026-49468 | < 1.84.0 | 1.84.0 | A crafted Host header makes the auth check evaluate a different route, giving unauthenticated access to management routes under specific conditions. CVSS 9.8. |
| CVE-2026-59822 | < 1.84.0 | 1.84.0 | A fabricated Authorization header triggers the MCP OAuth2 passthrough fallback, giving unauthenticated MCP access. CVSS 4.0: 8.8. |
| CVE-2026-84377 (GHSA-3cv6-jpf6-8222) | < 1.88.6 and the 1.89–1.96 branches | 1.88.6, 1.89.7, 1.90.7, 1.91.5, 1.92.2, 1.93.2, 1.94.3, 1.95.1, 1.96.2 | An authenticated user can point a request at their own api_base (SSRF) and receive the operator’s provider credentials. CVSS 6.5. |
| CVE-2026-93355 | up to 1.102.1 per the CVE record | not stated | JWT login trusts an unverified email claim, so a token from a trusted identity provider can take over another user’s account, including an admin. CVSS 8.1 in the record, 8.8 per OX Security. |
| CVE-2026-114612 | 1.91.0 to 1.104.0rc1, by branch | 1.100.4, 1.101.3, 1.102.2, 1.103.1, 1.104.0rc2 | An internal user reaches proxy_admin through salt-key reuse, then remote code execution through MCP stdio. CVSS 9.9. |
Two caveats from the sources. CVE-2026-93355 has no LiteLLM advisory and no fixed version in any record, and the CVSS scores differ between OX Security and the CVE record. The GitHub data for GHSA-3cv6-jpf6-8222 also gives inconsistent ranges, so rely on the fixed-version list. None of the sources we read report in-the-wild exploitation of these CVEs.
How a WAF helps, and where it doesn’t
To be clear first: a WAF can’t stop the 1.107.0 malware. It ran inside your own host at Python start-up and sent data out. A reverse proxy in front of your incoming traffic never sees that. Pinning, hashes and rotation are the defence.
What OpenWAF does for a LiteLLM gateway (or any AI API) that is reachable from the internet:
- Host header validation. The OpenWAF edge routes by
Hostand answers 421 Misdirected Request to any host that isn’t a configured name, before any filtering or contact with the origin. A craftedHostnever reaches LiteLLM through OpenWAF, which is exactly the upstream control LiteLLM’s advisory for CVE-2026-49468 recommends. - Protection for AI endpoints (Bots and AI agents). For paths such as
/v1/chat/completionsyou can set:- request-rate limits per IP or per session;
- a body size cap;
- fixed checks that reject runaway requests, such as very large
max_tokens, many parallel completions or thousands of messages; - prompt-injection detection.
- Rate rules and an access gate for the admin side. Put tighter rate limits on key and user management routes, restrict them by IP or country, or put the admin UI behind the access gate with one-time e-mail codes.
- An origin that only answers OpenWAF. With authenticated origin pulls (mTLS), the edge presents a client certificate and your server can refuse every connection that doesn’t come through OpenWAF, so these controls can’t be bypassed by hitting the origin directly. The client CA is shared across the platform: it proves the connection comes from the OpenWAF edge, not that it is for your zone, so keep checking
Hostas well.
Limits: the authenticated CVEs (42271, 47101, 47102, 84377, 114612) and the JWT takeover (93355) use valid credentials and normal-looking API calls, which no WAF can tell apart from real use. The SQL injection in CVE-2026-42208 sat in API key verification, where generic WAF rules may not look. Updating LiteLLM is the fix.
Checklist
- Find every LiteLLM install: servers, containers, CI images, notebooks and developer laptops.
- Check whether 1.107.0 or the affected image tags ran between 11:39 and 14:20 UTC on 21 October, using the commands above and your deploy and pull logs.
- On affected hosts, remove the startup files without running Python, then rebuild from a pinned, hash-checked version.
- Rotate the provider keys in the LiteLLM database, the master and virtual keys,
DATABASE_URL, cloud roles and every secret those hosts could read. - Review provider usage, CloudTrail and Git audit logs for activity after 21 October.
- Block and search for the IOCs at your egress proxy and DNS resolver.
- Make sure no LiteLLM older than 1.106.x is exposed anywhere. The 2026 CVEs make old versions dangerous even without the supply chain attack.
- Put the gateway behind a WAF that validates
Host, rate-limits the AI endpoints and gates the admin UI, and lock the origin to it.
Frequently asked questions
Was I affected by the LiteLLM 1.107.0 compromise?
Only if you installed litellm 1.107.0 from PyPI between 11:39 and 13:23 UTC on 21 October 2026, or pulled the Docker Hub or GHCR images tagged v1.107.0, latest, main-latest or main-stable between 11:46 and 14:20 UTC (GHCR was clean by 13:51). Images pulled in that window by a CI job or an autoscaler count too. LiteLLM says earlier versions, the GitHub source tag and the private enterprise registry were not affected.
I only installed LiteLLM and never imported it. Am I still at risk?
Yes. The malicious wheel dropped a .pth file that runs on every Python start, including pip itself, so the stealer ran as soon as any Python process started in that environment.
Which LiteLLM version should I run now?
On 21 October LiteLLM told users to pin 1.106.2 or another explicit version published before the incident. PyPI has since received 1.106.3 and 1.106.4 (24 and 25 October). All of them are newer than all the affected versions in the 2026 CVE table. Pin an exact version and verify its hashes rather than following latest.
Is uninstalling LiteLLM 1.107.0 enough?
No. Remove cook.pth, cook.py, sitecustomize.py and their compiled files, stop the loader process, and preferably rebuild the environment or image from scratch. If the host had outbound internet access, LiteLLM says to assume the data was stolen and rotate everything it could read.
Which secrets should I rotate?
Every provider key stored in the LiteLLM database, the master and virtual keys, the DATABASE_URL password, the instance or task cloud role, and any secret in the environment of any process on the host, plus SSH, GPG, Git and package registry tokens on that machine.
Were the 2026 LiteLLM CVEs exploited in the wild?
None of the advisories or reports we used say so. Several are critical, and some need no login, so update anyway: every 1.106.x release is newer than all the affected versions in the table.
Can a WAF protect LiteLLM?
Not against the 1.107.0 malware, which ran inside your own host and sent data out. In front of the proxy, a WAF that validates the Host header blocks CVE-2026-49468, as LiteLLM's own advisory says. Rate limits, body caps and an access gate also reduce what an attacker can try against an exposed gateway. Requests from a user with a valid key look legitimate to any WAF, so patching still matters.
Sources
- Contained: Oct 21, 2026 LiteLLM release v1.107.0 Compromised LiteLLM, Oct 21, 2026
- The attack chain behind the v1.107.0 LiteLLM release LiteLLM, Oct 23, 2026
- LiteLLM Hijacked Again: Malicious 1.107.0 Wheels Steal Credentials and Load Remote Code JFrog Security Research, Oct 21, 2026
- Inside the LiteLLM 1.107.0 supply chain compromise: credential theft through Python startup hooks Microsoft Security, Oct 23, 2026
- LiteLLM release pipeline hacked to distribute info-stealer malware BleepingComputer, Oct 22, 2026
- GHSA-4xpc-pv4p-pm3w: Authentication Bypass via Host Header Injection (CVE-2026-49468) LiteLLM, May 28, 2026
- GHSA-7488-6r32-c95q: MCP OAuth2 passthrough authentication bypass (CVE-2026-59822) LiteLLM, Jun 30, 2026
- GHSA-v4p8-mg3p-g94g: command execution via MCP stdio test endpoints (CVE-2026-42271) LiteLLM, Apr 21, 2026
- GHSA-r75f-5x8p-qvmc: SQL injection in proxy API key verification (CVE-2026-42208) LiteLLM, Apr 20, 2026
- GHSA-qrc4-49gv-mv9m: privilege escalation via allowed_routes (CVE-2026-47101) GitHub Advisory Database
- GHSA-wpfp-gwwc-vwq6: self role change via /user/update (CVE-2026-47102) GitHub Advisory Database
- GHSA-3cv6-jpf6-8222: SSRF and provider credential exfiltration (CVE-2026-84377) LiteLLM, Aug 26, 2026
- GHSA-7hp6-4w63-5g45: internal_user to proxy_admin and RCE (CVE-2026-114612) LiteLLM, Sep 30, 2026
- LiteLLM: an ordinary login token can become someone else’s admin account (CVE-2026-93355) OX Security, Sep 29, 2026
Topics
- LiteLLM
- LiteLLM 1.107.0
- supply chain attack
- PyPI
- AI gateway
- CVE-2026-49468
- CVE-2026-42208
- CVE-2026-93355
- MCP
Author
OpenWAF
