One package, all your keys: the LiteLLM release compromise
I write PHP and Node, and this is a Python incident. I am writing about it anyway because the pattern has nothing to do with the language: a library that sits in front of all your AI providers holds all their keys, so one poisoned release reaches every one of them. According to the pwn.watch incident tracker, that is what happened to LiteLLM on 21 October 2026.
What the tracker reports
This is the tracker's summary, one aggregator's account; the project's own advisory is what to check before you act. The tracker rates the entry critical and lists it as patched. It says attackers compromised LiteLLM's release pipeline and published a malicious litellm==1.107.0 to PyPI, live for about two hours, plus compromised Docker Hub and GHCR tags: v1.107.0, latest, main-latest and main-stable. Per the tracker, the wheels drop cook.pth, cook.py and sitecustomize.py, which steal cloud, developer and AI-tool credentials at every Python startup and open a remote-code loader. The tracker calls it the second LiteLLM compromise of 2026.
The latest tag is worth a second look. A container that pulls latest on restart did not need anyone to upgrade anything to receive this.
It may not be isolated, either. Railway, in its own disclosure the same day, says it believes its incident is part of a series of attacks on platform companies aimed at compromising AI inference providers.
Why an AI gateway is the target
General knowledge: a gateway or proxy library exists so your app can talk to many model providers through one interface. That means the process running it has every provider key in its environment at once. A normal dependency compromise gets the keys of one service. This one gets the keys of all of them, and AI keys are spend that someone else can run up.
The startup files make it worse. Also general knowledge, and documented Python behaviour: .pth files in site-packages are processed when the interpreter starts, and lines in them that begin with import are executed; sitecustomize also runs at startup. So a malicious wheel of this kind does not wait for your code to import the library. Any Python process in that environment runs it, including a one-off script or a test run.
For PHP and Node readers, the same shape applies to anything that holds many credentials: a wrapper around Stripe, Twilio or several AI SDKs, or a deployment CLI with access to every environment.
Containment that limits the damage
None of this stops a pipeline from being compromised. It limits what one bad release can reach.
Pin by version and hash. A version number alone does not stop a re-published or swapped file; a hash does. With pip, a requirements file that lists hashes and --require-hashes refuses anything else; uv and pip-tools lock files do the same job. Pin container images by digest rather than by a moving tag such as latest, and wait a few days before adopting a brand-new release. Isolate. Install and run the gateway in its own environment or container that holds only the keys it needs, and never install new packages on a machine that has production secrets loaded. Scope the keys. Give each provider a separate, short-lived key with a spend limit, so a stolen one is cheap and quick to replace.
pip install --require-hashes -r requirements.txt
pip show litellm
If 1.107.0 was installed or pulled
General order: take the environment or container out of service, check which version and which image tag actually ran, rebuild from a known-good pinned release, and rotate every key that environment could read, from a clean machine. The startup files mean any Python process there counts, not only the gateway. Confirm the affected versions and tags in LiteLLM's own advisory.
Source: the pwn.watch incident tracker, entry "LiteLLM 1.107.0 PyPI/Docker supply-chain compromise".
Notes from readers