Skip to content
The Injection_
LIVE
LIVElast sweep next in--:--:--

[ RSS ][ JSON ][ llms.txt ]

LiteLLM 1.107.0: backdoored wheels steal cloud and AI keys

LiteLLM 1.107.0 installed a credential stealer that runs whenever Python starts, even if nothing imports LiteLLM.

· Socket · Research by Socket Research Team, Guy Korolevski (JFrog Security Research)

LiteLLM
Cover image for Socket's analysis of the compromised LiteLLM release
CRITSupply chain

LiteLLM 1.107.0 on PyPI shipped a credential stealer in all seven wheels and in the v1.107.0 container images, Socket and JFrog report. PyPI quarantined the release; anyone who installed it should rotate every reachable secret.

01What happened

Socket's scanner flagged litellm 1.107.0 on PyPI about seven minutes after it was published on October 21, 2026, and JFrog published its own analysis the same day. All seven wheels carried a credential stealer, and the v1.107.0 container images carried the same payload. PyPI has quarantined the release and JFrog reports that Docker Hub removed the affected image.

02How it works

Three files land in site-packages: cook.pth, cook.py and sitecustomize.py. Python runs .pth files at interpreter startup, so the collector fires on any Python or pip command in that environment, not only when an application imports LiteLLM. What it gathers is encrypted with AES-256 and RSA-4096 and posted to a lookalike domain over plain HTTP. A second file starts a detached daemon that polls a file in a GitHub repository roughly hourly for a domain, then downloads and runs Python from that domain with no signature or hash check.

03Who is affected

Any environment that installed litellm 1.107.0 from PyPI, or pulled ghcr.io/berriai/litellm:v1.107.0 or a floating tag that briefly resolved to it, is exposed. JFrog also names the official litellm/litellm:1.107.0 image on Docker Hub. Socket notes that the macOS build's database and browser-password routines fail on typical macOS systems, while its other modules still run.

04What to do

Isolate any host or container that ran it and treat every secret it could read as exposed, including LiteLLM master and virtual keys and the upstream provider keys in LiteLLM_CredentialsTable. Delete cook.pth, cook.py and sitecustomize.py with tools that do not start the affected interpreter, kill any detached Python process holding /tmp/remote_code_loader.lock, then rebuild and pin litellm 1.106.2.

Questions people ask

Am I affected if my code never imports LiteLLM?
LiteLLM 1.107.0 installs a .pth file, and Python executes .pth files at interpreter startup, so the stealer runs in any environment holding the package even when no application imports it. Socket and JFrog both note that an ordinary pip command is enough to trigger it. Treat the whole environment as compromised, not only the application that depends on LiteLLM.
Which LiteLLM version is safe to pin?
JFrog recommends pinning litellm 1.106.2, and the PyPI quarantine notice for 1.107.0 points at the same release. Socket says it did not certify any earlier artifact as clean, so pinning should go together with rebuilding from a reviewed artifact. Container images deserve pinning by digest too, because floating tags briefly resolved to the compromised build.
Which credentials does the LiteLLM stealer take?
The collector reaches SSH, GPG and TLS private keys, AWS, Azure and Google Cloud credentials, Kubernetes configs and service-account tokens, CI and infrastructure-as-code secrets, npm and PyPI configs, and browser password and cookie stores. It also reads the auth files of AI tools including Codex, Claude, Cursor, Copilot and Hugging Face, and where DATABASE_URL is set it queries the LiteLLM proxy's stored provider keys.
Does uninstalling the litellm package stop the stealer?
Removing litellm leaves cook.pth, cook.py and sitecustomize.py behind in site-packages, so the startup hook keeps running. JFrog says to delete those files and their compiled __pycache__ entries, along with /tmp/.pc_once_72129118c59f5636c0bb and /tmp/remote_code_loader.lock, using tools that do not invoke the affected interpreter, and to find and kill any detached Python process still holding the lock.
How did the payload reach PyPI if the Git tag is clean?
JFrog reports that the source tarball and Git tag do not contain the three payload files, while the sdist's pyproject.toml carries an added Maturin setting the tag lacks, and says the exact injection point is unknown. Socket found that the malicious container build's provenance names Berri-AI/litellm, one hyphen from the real BerriAI/litellm, and says the authorization behind that override remains unestablished.

Sources 3 links, all fetched

  1. 1socket.devSocket Analysis
  2. 2research.jfrog.comJFrog Analysis
  3. 3pypi.orgPyPI Quarantine