The Package That Knew Where the Keys Were
Most credential stealers search a laptop for whatever they can find. The one shipped in LiteLLM 1.107.0 knew exactly where to look. LiteLLM Proxy keeps upstream provider keys in a Postgres table, and the malware ran a query against that table to pull up to 500 of them.
That is the risk with an LLM gateway. Its job is to hold provider and cloud credentials in one place, so one poisoned install can expose many of them at once. And this payload didn’t stop at stealing. It also carried a loader built to download and run more code later.
This post covers what happened on October 21, where LiteLLM tends to show up, and how Cycode helps, starting at the developer workstation where the install happens.
What Happened on October 21
LiteLLM 1.107.0 was malicious on PyPI and in the official Docker images. The last safe version is 1.106.2. BerriAI, the company behind LiteLLM, says the attacker used stolen GitHub CLI OAuth tokens from three engineers. One account triggered the release workflow and another approved it.
| Time (UTC) | What happened |
|---|---|
| 08:56 to 10:46 | Ten attacker commits add cook.pth, cook.py and sitecustomize.py, bump the version, and add the files to the wheel build and Dockerfiles |
| 11:39 | 1.107.0 uploaded to PyPI |
| 11:43 | AISLE flags the first wheel, about 3 minutes after upload |
| Early afternoon | PyPI quarantines the release |
| About 13:53 | Poisoned Docker tags removed: v1.107.0, latest, main-latest, main-stable |
The payload doesn’t wait for you to import LiteLLM. The .pth file and sitecustomize.py run whenever any Python interpreter starts in that environment. The stealer goes after cloud credentials (AWS, GCP, Azure), LLM provider keys, SSH and GPG keys, browser cookies, shell history, and the LiteLLM credentials table.
It also includes a backdoor. On Linux and macOS, sitecustomize.py checks a GitHub dead drop for a domain on an hourly loop, then downloads and runs a second-stage Python script from it. Researchers found the dead drop empty when they looked. Even so, treat any machine that ran 1.107.0 as open to remote code execution, not just credential theft.
The latest tag matters here. Any image that pulled litellm/litellm:latest during that window got the malware without anyone choosing 1.107.0.
Where LiteLLM Hides
Ask a team whether they use LiteLLM and you’ll often hear “no.” Then you find it in four places.
| Where it shows up | How it gets there | Why it was exposed |
|---|---|---|
| Transitive dependency | Agent and LLM frameworks such as DSPy and CrewAI pull it in | Nobody on the team chose it, so nobody watched it |
| Loose version ranges | litellm>=1.80 in requirements.txt or pyproject.toml, with no lockfile | Any fresh install that day resolved to 1.107.0 |
| Proxy containers | FROM litellm/litellm:latest or a Helm chart on a floating tag | Pods that restarted or scaled during the window pulled the bad image |
| CI runners and dev machines | pip install in a job or a notebook | These hold the richest secrets: deploy keys, cloud roles, tokens |
The last row is the one most teams underestimate. A CI job that installs dependencies and also has a cloud deploy role is exactly what this stealer was built to rob.
How Cycode Helps
This attack had two halves: a poisoned package, and a release pipeline that trusted stolen tokens. Cycode has controls for both, starting with the one closest to the install.
Stop it at the install. Cycode Workstation Protection, now in early access, deploys through MDM and checks each package install on developer and citizen developer machines in real time, whether a person or a coding agent runs it. A cooldown policy holds back versions published too recently, so a release only hours old, like 1.107.0, would be held on covered machines under a policy of a few days. A separate check against Cycode’s threat intelligence feed blocks known-malicious versions even after a cooldown ends. Protection applies where the agent runs, so CI runners and build containers need it installed there too.
Find copies across connected sources. Cycode builds SBOMs and AIBOMs for the repos it’s connected to, so LiteLLM shows up as a direct dependency or as one pulled in by an agent framework. Container scanning does the same for images in connected registries, including litellm/litellm proxy images on floating tags. Anything outside those sources, like an unmanaged laptop or a one-off notebook, needs another way to find it.
Tie each hit to an owner. The Context Intelligence Graph links a finding to its repo, image, pipeline and team. One query lists where litellm==1.107.0 shows up across connected sources and who needs to act.
Start the credential investigation. Cycode’s secrets detection scans code, CI/CD, build logs, Kubernetes, Slack, Teams and Confluence. It can point to provider keys and cloud credentials that sat near an affected environment, which gives the investigation a starting list. It won’t see secrets that only lived in environment variables, local config or the LiteLLM database, so treat everything reachable from an infected host as exposed.
Watch the build, not just the code. Cimon, Cycode’s eBPF-based build monitor, watches network calls, file changes and processes on CI runners. A job that suddenly writes .pth files into site-packages or posts to www.litellm.dev is the kind of behavior it exists to catch.
Close the door the attacker used. Cycode’s CI/CD posture checks cover how your own pipelines are set up: who can trigger a release, who can approve it, and which tokens can do both. The LiteLLM release went out because one stolen account started the workflow and another approved it. That pattern is worth checking in your own repos today.
A First-24-Hours Plan
- Right now: contain. Pin LiteLLM to 1.106.2 and block 1.107.0 in your package proxy or Workstation Protection. Stop workloads running affected images, isolate hosts, runners and laptops that installed 1.107.0, and block traffic to
litellm.dev. - Right now: rotate. Don’t wait for the investigation to finish. Revoke and reissue every key in the LiteLLM credentials table, plus cloud roles, CI tokens, SSH keys and developer tokens on affected machines. Use secrets findings to add to that list, not to shorten it.
- Next: scope the exposure. Query the graph for
litellm==1.107.0in SBOMs, lockfiles and images, including anything built fromlatest,main-latestormain-stableon October 21. Ask teams directly about machines Cycode isn’t connected to. - Next: check for the backdoor. Look for
cook.pth,cook.pyorsitecustomize.pyinsite-packages, the marker file/tmp/.pc_once_72129118c59f5636c0bb, and outbound calls that fetched more code. Rebuild affected environments instead of cleaning them, since a second stage may have run. - After: stop the next one. Turn on a cooldown policy, pin versions with hashes in lockfiles, replace floating image tags with digests, and review who can trigger and approve your own release workflows.
The Gateway Is Now a Target
AI gateways were built to make life simpler: one place for every model, every key and every budget. That also makes them one place to rob. This is the second LiteLLM supply chain incident this year, after the 1.82.8 wheel in March.
The teams that came through today fine had pinned versions, short-lived credentials and a clear view of where LiteLLM ran. Cycode is built to give you that view before the next release goes bad, not after.
Sources
- LiteLLM: Security incident, October 21, 2026
- AISLE: Compromised LiteLLM Package Found 3 Minutes After Release
- Cybersecurity News: LiteLLM 1.107.0 Compromised
- Caido docs: March 2026 litellm 1.82.8 warning
- Cycode: Introducing Workstation Protection
- Cycode: ADLC Security Platform
- Cycode: Context Intelligence Graph with AI
- SC Media: Cycode Cimon for CI/CD security