LiteLLM 1.107.0 Compromised: Who Is Exposed and What to Rotate First

Share

On 21 October 2026, LiteLLM published an incident report confirming that litellm 1.107.0 on PyPI was malicious. The package stayed online for about two hours, from 11:39 to 13:23 UTC.

Four Docker Hub tags, including latest, served a poisoned image until 14:20 UTC. The official source tag was clean: the attacker built the release from a lookalike repository.

In short, litellm 1.107.0 is a malicious release that steals credentials from any host that installed it. LiteLLM’s advice is blunt: treat that machine as compromised and assume its secrets are gone.

At a glance

  • What happened: seven malicious wheels of litellm 1.107.0 reached PyPI, and a poisoned image reached Docker Hub and GHCR.
  • Exposure window: 21 October 2026. The PyPI wheels were live from 11:39 to 13:23 UTC. The Docker Hub tags stayed poisoned until 14:20 UTC.
  • What it does: a startup hook runs on every Python launch and steals keys and cloud credentials once per host; a second hook installs an hourly remote-code loader.
  • Safe versions: 1.106.2 and the 1.107.0 release candidates. Enterprise customers on the private registry were not affected.
  • First move: do not run pip install on an exposed host. Delete the hook files, kill the daemon, rebuild, then rotate every reachable secret.

Which litellm 1.107.0 packages and images were compromised?

Only one Python version is affected. LiteLLM’s timeline says seven malicious wheels were uploaded in a burst starting at 11:39:51 UTC. PyPI had removed them by 13:23.

Today the PyPI project page lists 1.106.2 as the latest release. The metadata endpoint for the bad version returns 404.

The container side lasted longer. Docker Hub tags v1.107.0, latest, main-latest and main-stable pointed to a bad image index. Its digest starts with sha256:1bbcb144, and the full value is in the report.

On GHCR, the GitHub Container Registry, the litellm, litellm-database and litellm-non_root images were found unavailable at 13:51 UTC.

ChannelAffected artifactWindow (UTC, 21 Oct 2026)Status now
PyPIlitellm==1.107.0, seven wheels11:39 to 13:23Removed
Docker Hubv1.107.0, latest, main-latest, main-stable11:46 to 14:20v1.107.0 removed, others repointed
GHCRlitellm, litellm-database, litellm-non_rootFrom 11:46; unavailable by 13:51Unavailable
Enterprise registryPrivate releaseNot affectedNot affected

The security issue on GitHub also lists what stayed clean. That covers 1.106.2 and both release candidates of the bad version. SafeDep also found the pinned companion packages clean: litellm-proxy-extras 0.4.110 and litellm-enterprise 0.1.78.

How long each LiteLLM 1.107.0 channel served malicious code: PyPI wheels, Docker Hub tags
How long each LiteLLM 1.107.0 channel served malicious code · Source: docs.litellm.ai

How many teams could have pulled the bad release?

LiteLLM is a gateway: one OpenAI-compatible endpoint in front of many model providers. That role makes it a dense store of API keys. When we checked on 22 October, the BerriAI/litellm repository had 61,780 stars. It also had 12,565 forks.

Download numbers show how wide the funnel is. PyPI Stats counted about 3.4 million downloads on its latest full day. The weekly total was about 22.8 million.

Those are all versions, mostly from CI pipelines and mirrors. Nobody has published how many installs hit 1.107.0 during the window. Any build that resolved an unpinned litellm in those two hours would have fetched it.

What does the malicious code do on an infected host?

The payload uses two Python startup hooks. A .pth file, a path file that site-packages executes at interpreter start, runs on every Python launch. Your code does not need to import litellm.

1. The credential stealer in cook.pth

According to SafeDep’s analysis, cook.pth loads cook.py and sweeps the host. It takes SSH keys, cloud and Kubernetes credentials, Docker and GitHub CLI configs, .env files and private keys. It also reads config files of AI coding tools such as Claude, Codex, Gemini and Cursor.

The GitHub issue adds two details that matter for proxy operators. If DATABASE_URL is set, the stealer dumps the LiteLLM credentials and model tables through Prisma, the proxy’s own database client. It also validates AWS credentials with an STS GetCallerIdentity call, the AWS request that returns which account a key belongs to.

The loot is encrypted with AES-256-CBC, and the key is wrapped with an RSA public key. It is then posted to www.litellm.dev/healthcheck. That domain is not LiteLLM’s: the issue says it was registered on 13 October 2026.

2. The hourly loader in sitecustomize.py

Python imports sitecustomize at startup too. Here it forks a detached daemon that holds /tmp/remote_code_loader.lock. Every hour it reads a domain from a text file in an attacker’s GitHub repository, reruns the stealer, then downloads and executes code from that domain.

SafeDep reports that the attacker’s GitHub account returned 404 at 13:40 UTC. The loader therefore has no server to call.

SafeDep says hosts that ran the daemon earlier could have fetched second-stage code. The GitHub issue weakens that risk: the dead-drop file, the public text file the loader reads for its next server, had been empty since 09:15 UTC on 20 October, the day before the release.

How did attackers publish through a hardened pipeline?

This was not a stolen PyPI password. After a previous incident in March, LiteLLM moved releases to a private repository.

It also adopted PyPI Trusted Publishing, which lets a CI workflow publish without a long-lived password. It made Docker release tags immutable and signed its images with Cosign.

The attacker went around those controls with valid developer sessions. LiteLLM’s report describes three GitHub CLI OAuth tokens, including one held by one of its two organization owners. That token was used to disable branch protections and force-push the workflow change.

LiteLLM also says it had temporarily widened release permissions on Monday, 19 October, so two engineers could publish daily backports. At 10:08:34 UTC on the day of the attack, one credential changed the private release workflow. At 11:11:18 a second account satisfied the production approval gate.

The workflow then built artifacts from Berri-AI/litellm, a lookalike of the real BerriAI organization. A third account deleted the workflow records at 11:53 UTC. That limited the logs left for investigators.

Where did the stolen GitHub tokens come from?

LiteLLM points at its own product. An internal LiteLLM deployment was exposed to the public internet. The team found an unexpected, innocuously named user account on it.

The report says Claude Code can, in specific situations, embed a GitHub CLI OAuth token in a response body. When a gateway logs response bodies, that token lands in the logs. LiteLLM believes the attacker read those logs and reused the tokens.

How the attacker got into the deployment is still open. LiteLLM suspects a recently patched vulnerability but has not confirmed it. The lesson does not depend on that answer: request and response logs on an AI gateway can hold credentials, not just prompts.

What should you do if you installed 1.107.0?

Start by checking, not reinstalling. pip show litellm reports the installed version. Then search the filesystem for litellm-1.107.0.dist-info, cook.pth and sitecustomize.py.

LiteLLM warns that a missing file proves nothing, because container restarts and temp cleanup erase evidence. Finding one, by contrast, confirms exposure.

These three read-only shell commands cover the quick check without starting Python:

find / -name 'cook.pth' -o -name 'sitecustomize.py' -o -name 'litellm-1.107.0.dist-info' 2>/dev/null
ls -la /tmp/.pc_once_* /tmp/remote_code_loader.lock 2>/dev/null
pgrep -af python

Some Python distributions ship their own sitecustomize.py, so inspect any match before deleting it.

The remediation steps in the GitHub issue, endorsed by LiteLLM, run in this order:

  1. From the shell, not Python, delete cook.pth, cook.py, sitecustomize.py and their cached .pyc files in every site-packages.
  2. Kill the detached Python daemon holding /tmp/remote_code_loader.lock.
  3. Pin litellm==1.106.2. Rebuilding images and virtual environments from scratch is better.
  4. If the host had outbound internet, assume the theft succeeded.
  5. Rotate the instance IAM role (the cloud identity attached to the machine), every provider key in the proxy database, the master and virtual keys, and the database password.
  6. Search CloudTrail for GetCallerIdentity calls from the instance role around install time.

Step one matters most. Running pip on an infected host starts Python, and that fires both hooks again.

Teams that run agents with broad credentials face a wider blast radius. Our containment test for files, network, credentials and persistence covers what a host like this can reach. A container alone is no fence either, as our piece on why a container is not an agent permission model explains.

Which indicators should security teams search for?

The GitHub issue lists the indicators of compromise, the traces an attack leaves behind. Network teams should look for POST requests to www.litellm.dev/healthcheck carrying the header X-Token: XWiA8gZNa7NcX2XRoAEb. Endpoint teams should look for these host markers:

  • cook.pth, cook.py and sitecustomize.py in any site-packages directory.
  • The file /tmp/.pc_once_72129118c59f5636c0bb, written only after a successful upload of stolen data.
  • The lock file /tmp/remote_code_loader.lock and an orphaned Python process whose working directory is the root.
  • On Windows, sitecustomize.py cannot fork and fails silently, but cook.py still runs, so the stealer markers apply there too.
  • The environment variable PRIVCOLLECT_ACTIVE=1 and temporary folders named /tmp/.pc_sq_* or /tmp/.pc_e_*.

The issue also names the GitHub account letters9813 as the dead drop. It was created on 13 October 2026, the same day as the fake domain. Neither date proves when the attack was planned, but both predate the release.

What should gateway operators change after this?

Three changes follow directly from LiteLLM’s own account. First, pin exact versions and verify hashes in CI. An unpinned dependency resolved during the window was enough to pull the bad wheel.

Second, treat gateway logs as secret stores. If your proxy logs full response bodies, restrict who can read them, shorten retention and scan them for tokens. Third, keep internal admin panels off the public internet, whatever the vendor’s patch status.

The same trust problem applies to agent plugins and skills, which we covered in why MCP plugin catalogs need a security gate. A one-click install and an unpinned pip install fail in the same way.

Is LiteLLM safe to install again?

The current public packages are the clean ones. PyPI serves 1.106.2, and LiteLLM says the moving Docker tags now point at secure sources. It has also cut maintainer credentials down to the minimum while it investigates.

The safest path is still to pin an exact version and, for containers, an image digest rather than a tag.

LiteLLM’s report also mentions a separate vulnerability. Its fix ships in an embargoed release that only Enterprise customers receive for now, with disclosure planned for 27 October 2026. Teams on the open-source build should watch the incident page for updates, since LiteLLM says more detection guidance is coming.

What we could not verify

This article reflects LiteLLM’s report as last updated on 21 October at 20:30 UTC.

No one has published the number of installs of 1.107.0 during the window. PyPI Stats does not break down the latest day by version in a way we could check. LiteLLM has not confirmed how the attacker entered its internal deployment.

We could not check whether second-stage code reached any host before 13:40 UTC, though the empty dead drop makes it unlikely. Anthropic had not commented on the token behavior LiteLLM describes when we checked. We have not seen any details of the embargoed vulnerability, and LiteLLM has not said whether open-source users are exposed to it.

Sources

Maya Chen
Maya Chen
Maya Chen covers AI agents, orchestration frameworks, tool-use, and evaluation. She focuses on what actually works in production—failure modes, safety boundaries, and measurable performance—without the hype.

Read more

Local News