TL;DR: LiteLLM 1.107.0, the Python SDK and proxy that puts many AI model providers behind one API, was published to PyPI and Docker on October 21, 2026 with a credential stealer inside. The issue’s reporter and StepSecurity say the malware runs on every Python start in an environment where 1.107.0 is installed, even if nothing imports litellm; the reporter says it collects cloud, SSH and AI tool credentials, environment variables and the provider API keys stored in a LiteLLM proxy database. BerriAI, which maintains LiteLLM, says the package and the malicious Docker images have been removed, that the attacker used stolen GitHub CLI tokens to run its release workflow, and that it has locked its registries to new releases. BerriAI’s account of the attack chain says the first of those tokens was reached through the master key to an internal agent service, which had been committed to a public repository in May and never revoked. If you installed 1.107.0, or ran a v1.107.0, latest, main-latest or main-stable image pulled between 11:46 and 14:20 UTC (7:46 and 10:20 p.m. Manila) on October 21, treat that machine as compromised: clean it up, rebuild clean on 1.106.2 (or an earlier explicit version) and rotate every key it could reach.
Update, Oct 29, 2026, 8:05 a.m. Manila: BerriAI has disclosed a separate flaw in the LiteLLM proxy with an Enterprise license that can leak the master key and provider API keys. It affects 1.106.2, the version this story says to pin, and is fixed in 1.106.5. If you run the proxy with an Enterprise license, update to the fixed release for your line instead of staying on 1.106.2; our story on the LiteLLM Enterprise proxy key leak lists every fixed version.
Update, Oct 24, 2026, 6:20 a.m. Manila (22:20 UTC Oct 23): BerriAI has published the attack chain behind the v1.107.0 release, dated October 23, and says it has completed its investigation. It says some assumptions in its earlier status updates “were later proven to be inaccurate or incomplete” and that “[t]his post is the canonical source of truth.” According to the post, on May 27 a configuration file committed to the public LiteLLM-Labs/lite-harness repository “inadvertently contained the master key to a deployment of the LiteLLM Agent Platform,” an internal agent tool; the commit was force-pushed over, but “key revocation did not occur.” On October 10 the attacker used that key to call the Agent Platform’s API, and the response contained the GitHub CLI OAuth token of one of BerriAI’s GitHub organization owners. BerriAI says that token “was not associated with a service account and was not scoped down.” With it, the attacker pushed throwaway branches whose CI workflows sent repository secrets to an outside endpoint, including the GitHub CLI tokens of two maintainers, which were later used to approve the production release and delete its run records. BerriAI also says a rule requiring release approval from a special account locked to a device in its office had been relaxed earlier that week so that any two engineers could trigger and approve a release. BerriAI said in the post that it expected to “safely issue a release by EOD today”; when we checked at 6:20 a.m. Manila on October 24, PyPI’s latest version was still 1.106.2. BerriAI says it will share its process changes next week. We’ve corrected the how-it-got-in section and rewritten step 6 of what to do; see the correction below.
Correction, Oct 24, 2026, 6:20 a.m. Manila: An earlier version of this story said BerriAI believed the stolen GitHub tokens were taken from the logs of an internal LiteLLM deployment exposed to the internet, and step 6 of what to do was based on that. BerriAI’s October 23 attack-chain post says that was its first suspicion and that “[t]he request logs show the first token came from a different service”: the LiteLLM Agent Platform, reached with a master key that had been committed to a public repository on May 27. We’ve corrected the how-it-got-in, what-to-do and still-unknown sections.
Update, Oct 23, 2026, 7:45 p.m. Manila (11:45 UTC): BerriAI has stopped posting updates every two hours and now says it will post updates “when there are significant developments to share.” In a 02:19 UTC update on October 22 (10:19 a.m. Manila), it said: “The investigation is ongoing, and we have no material developments to report since our last update. Our registries remain locked to new releases, and regular LiteLLM releases remain paused.” It added: “We are moving from scheduled two-hour updates to updates when there are significant developments to share.” Its update before that, at 23:37 UTC on October 21 (7:37 a.m. Manila on October 22), said it was “identifying every authentication token across our organization and revoking or rotating each one,” and that “[f]or the vast majority of these tokens, we have seen no indication of exfiltration or improper use.” BerriAI posted again at 15:54 UTC on October 22 (11:54 p.m. Manila), from the GitHub account of Krrish Dholakia, whose profile gives the title “CEO Berri AI.” That reply says enterprise customers pulling images from BerriAI’s private registry “are not impacted,” that “[t]he impacted version (v1.107.0) was removed within 3 hours of release,” and that “[o]lder versions of LiteLLM are not impacted.” It says BerriAI is continuing its root cause investigation, “will share the specific changes we’re making to harden our release pipeline,” and would host a town hall “tomorrow”; it doesn’t give a time in the issue. BerriAI hasn’t posted in the issue since. Its incident post still shows “Last updated: October 21, 2026 20:30 UTC” and still says BerriAI will “continue to update every two hours.” The post also says BerriAI’s private enterprise registry carries “an embargoed release that remediates a vulnerability whose disclosure date is scheduled for October 27”; it doesn’t say which versions are affected or when open-source users will get a fix. Our take: while regular releases are paused, stay pinned to 1.106.2 or another explicit earlier version, and watch for the vulnerability disclosure that BerriAI’s incident post says is scheduled for October 27, which may mean you need to update again once releases resume. When we checked, PyPI’s latest version was still 1.106.2, and the Docker Hub and GHCR latest, main-latest and main-stable tags still matched v1.106.2.
Correction, Oct 23, 2026, 7:45 p.m. Manila: An earlier version of this story, last updated at 7:24 a.m. Manila on October 22, said BerriAI would keep posting updates every two hours. BerriAI stopped its two-hour schedule at 02:19 UTC on October 22 (10:19 a.m. Manila). We’ve fixed that in the status and still-unknown sections.
Update, Oct 22, 2026, 7:24 a.m. Manila (23:24 UTC Oct 21): BerriAI has published an incident post and posted four more updates in the GitHub issue. It says the attacker used stolen GitHub CLI OAuth tokens from three engineers’ accounts: one belonging to a GitHub organization owner was used to disable branch protections and force-push a change to its private release workflow, and a second account approved the production run, which built from the lookalike Berri-AI/litellm repository. At the time, BerriAI believed the tokens were taken from the logs of an internal LiteLLM deployment; it has since said the first token came from a different service (see the October 24 correction). BerriAI says it has revoked the tokens, removed all but one user from its GitHub organization, removed its registries’ trusted links to that organization and locked the registries to new releases, so ordinary LiteLLM releases are paused. Its incident post gives the exposure windows as 11:39 to 13:23 UTC on PyPI and 11:46 to 14:20 UTC on Docker Hub (7:39 to 9:23 p.m. and 7:46 to 10:20 p.m. Manila on October 21); the GHCR tags were unavailable by 13:51 UTC. Wiz says it has seen attackers testing stolen AWS instance-role credentials between 16:20 and 17:01 UTC (12:20 to 1:01 a.m. Manila on October 22). We’ve updated the status, how-it-got-in, what-to-do and still-unknown sections.
What happened
Status as of Oct 24, 2026, 6:20 a.m. Manila (22:20 UTC Oct 23): PyPI no longer serves 1.107.0, and its latest version is still 1.106.2; BerriAI said on October 23 that it expected to issue a new release that day. BerriAI’s incident post names v1.107.0, latest, main-latest and main-stable as the affected Docker tags and says v1.107.0 was removed and the others were pointed at clean images. When we checked Docker Hub (litellm/litellm) on October 24, v1.107.0 wasn’t found and latest, main-latest and main-stable had the same digest as v1.106.2; on October 23 the GitHub Container Registry (GHCR: ghcr.io/berriai/litellm, litellm-database and litellm-non_root) showed the same. BerriAI says its registries remain locked to new releases and regular releases remain paused, and that it now posts updates “when there are significant developments to share.” This is a moving story; we’ll update it.
The compromise was reported at 12:06 UTC (8:06 p.m. Manila) in issue #47826 on BerriAI’s GitHub repository, by Lidor Machluf of the Upwind security research team. The issue and StepSecurity’s analysis describe the same chain of events (times UTC; in Manila, 8 hours ahead, it all fell between 7:39 and 10:32 p.m. on October 21):
- 11:39 to 11:40: 1.107.0 was uploaded to PyPI. All seven 1.107.0 wheels (macOS, Linux and Windows) carry three extra files,
cook.pth,cook.pyandsitecustomize.py, that pip installs into the root of site-packages. The source package (.tar.gz) has a tampered build config but not the payload files. - 11:48: StepSecurity says the infected image was pushed to Docker Hub, and the
latest,main-latestandmain-stabletags pointed to it. The issue’s reporter found the same payload files, byte-identical, in thev1.107.0images forghcr.io/berriai/litellm,litellm-databaseandlitellm-non_rootand indocker.io/litellm/litellm. StepSecurity says the floating tags pointed to the infected image “for about three hours”; BerriAI’s incident post says the Docker Hub tags did so from 11:46:56 to 14:20 UTC and the GHCR tags until 13:51 UTC. - By 13:23: the reporter said PyPI had removed 1.107.0. At 13:50 UTC, BerriAI said: “We are actively investigating and treating this as SEV-0. PyPI quarantined 1.107.0.”
- 14:32: BerriAI said the malicious Docker images had been removed. “We have not yet identified or locked down the method by which the threat actor published the malicious release. This is where our current efforts are focused.”
How it got in: the payload isn’t in the v1.107.0 git tag. The reporter says the release was built from commits stacked on top of the tag in a lookalike repository, Berri-AI/litellm (with a hyphen), and StepSecurity says the build provenance attached to the v1.107.0 Docker images names that lookalike repository as the source. BerriAI says the attacker used a GitHub organization owner’s stolen token to override branch protections and push a change that pointed its release workflow at the lookalike repository, then used a second maintainer’s token to approve the production run and a third maintainer’s token to delete the run records. Its attack-chain post traces the owner’s token to the LiteLLM Agent Platform, an internal agent tool: its master key was committed to a public repository on May 27 and never revoked, and on October 10 the attacker used it to read the platform’s API, which returned the owner’s GitHub CLI token that the platform used to open pull requests. The same day, the attacker used that token to push throwaway branches whose CI workflows posted repository secrets, including the two maintainers’ GitHub CLI tokens, to an outside endpoint.
What the malware does, according to the reporter’s analysis of the decoded payload (they say nothing was executed):
- The reporter says
cook.pthmakescook.pyrun “on every start of that interpreter or venv,” andsitecustomize.py“also runs automatically at startup.” That includes running pip in that environment. cook.pyis a stealer that collects, among other things, SSH keys and shell histories; AWS, Azure, Google Cloud, Kubernetes, Docker and GitHub CLI credentials;.envfiles and private keys; CI and Vault secrets; “AI tool credentials and configs” for tools including Claude, Codex, Gemini, Cursor and Copilot; browser passwords and cookies; “the environment variables of every readable process”; and cloud instance credentials. IfDATABASE_URLis set, it dumps the LiteLLM proxy’s stored credentials and model tables, “i.e. every upstream provider key the proxy stores.” It encrypts the bundle and sends it tohttp://www.litellm.dev/healthcheck, which the reporter notes is not LiteLLM’s domain (litellm.ai).sitecustomize.pystarts a background process that checks a GitHub file every hour and, if it holds a domain, downloads and runs Python code from it. The reporter said that file was empty, so this stage was “dormant for now”; StepSecurity says the GitHub account behind it was later deleted. On Windows this part fails, butcook.pystill runs.
Why it matters
LiteLLM often sits in the middle of a team’s AI stack, holding the API keys for every model provider it routes to, on laptops, in CI and on production gateways. Researchers say the stealer runs at every Python start, so your code wouldn’t need to use litellm: installing it would be enough. StepSecurity notes that many projects depend on LiteLLM with an open-ended litellm>= constraint, so “a fresh install or lockfile refresh would have picked up 1.107.0,” and proxies that track the latest or main-stable image picked it up on their next pull or restart. It also says this is the second LiteLLM compromise on PyPI this year, after versions 1.82.7 and 1.82.8 in March.
What to do now
- Find out whether 1.107.0 ever reached you. Check lockfiles and requirements (
uv.lock,poetry.lock,requirements*.txt) for1.107.0, CI logs from October 21 for installs oflitellm-1.107.0, and any container that ran a LiteLLM image pulled on October 21 (v1.107.0,latest,main-latestormain-stable); BerriAI says any container that ran image digestsha256:1bbcb1443bc9…(the full digest is in its incident post) should be treated as compromised. On a machine, look in site-packages forcook.pth,cook.pyandsitecustomize.py. Do this from the shell: the reporter warns, “Don’t start withpip install,” because, the reporter says, any Python start in an affected environment runs the payload again. The marker file/tmp/.pc_once_72129118c59f5636c0bbmeans data was sent; if it’s missing, the reporter says “that proves nothing.” - If you were affected, clean up first. From the shell, delete
cook.pth,cook.pyandsitecustomize.py, plus any matching.pycfiles in__pycache__, from every affected site-packages, and kill the detached Python process holding/tmp/remote_code_loader.lock. The reporter lists deleting the files first; StepSecurity lists killing the process first. Both say rebuilding environments and images from scratch is better than cleaning in place. - Rebuild clean on 1.106.2 (or an earlier explicit version) and rotate every key. Don’t just change the version number on an affected machine: rebuild environments and images from scratch on 1.106.2 or an earlier explicit version, then rotate keys as in step 4. BerriAI says: “please pin your version to 1.106.2 or any explicit version published prior to now.” Both sources say to pin the
v1.106.2image by digest, not by a floating tag. StepSecurity says some PyPI mirrors kept serving cached 1.107.0 files after PyPI removed it, so purge 1.107.0 from any internal mirror, cache or registry. - Rotate everything the machine could reach. The reporter says that if 1.107.0 was ever installed on a host with internet access, “assume the exfil succeeded.” Rotate cloud keys and instance roles, SSH and GPG keys, GitHub, npm and PyPI tokens, CI and Vault secrets, AI tool tokens and saved browser passwords. On LiteLLM proxy hosts, rotate every provider API key stored in the proxy, the LiteLLM master and virtual keys, and the
DATABASE_URLpassword; StepSecurity adds the salt key. - Check your logs. The reporter suggests checking AWS CloudTrail for
GetCallerIdentitycalls from the instance role around install time, then for use of those credentials from outside your infrastructure. StepSecurity suggests searching network logs forlitellm.dev, for requests toraw.githubusercontent.comunder theletters9813account and for any path ending in/codepy, and blockinglitellm.dev. Wiz lists168.100.8.57and165.227.201.8as the addresses that tested stolen AWS credentials; search CloudTrail for them. - Check what your AI agents and gateways can hand out. BerriAI says the attack started with an agent platform’s master key that was committed to a public repository and never revoked, and that platform’s API returned a GitHub organization owner’s unscoped GitHub CLI token. If a key is ever committed or posted publicly, revoke it right away: force-pushing over the commit doesn’t undo the exposure. Give agents, AI gateways and other automation their own narrowly scoped tokens, such as a GitHub App or a service account limited to the repositories they need, never a person’s or an owner’s token. Check whether any admin API or dashboard of a tool you run returns stored credentials, keep admin interfaces off the public internet, and search your public repositories for committed config files that hold keys (GitHub CLI’s OAuth tokens start with
gho_). Anyone who can push a branch that runs your CI can read the secrets that CI exposes, so limit secrets to protected branches or environments. - Shorten the life of GitHub CLI tokens. On October 21, GitHub put expiring, auto-refreshing GitHub CLI tokens into public preview: with
ghv2.103.0 or later,gh auth login --expiringmeans “a leaked access token becomes unusable within hours instead of lasting indefinitely.” GitHub says scripts that save the output ofgh auth tokenfor later will break, so read it fresh each time.
LiteLLM’s enterprise customers who pull from its private registry aren’t affected, BerriAI says. For a way to stop brand-new package versions reaching CI automatically, see our story on GitHub’s package firewall and npm cooldowns; the same idea, waiting a few days before accepting a new release, would have kept 1.107.0 out of many installs.
What’s still unknown
BerriAI says it has completed its investigation and will share what it’s changing next week. It says ordinary releases are paused until it can show its registries can safely accept them again; for now, it asks open-source users to pin 1.106.2 or another explicit version published before its statement. It hasn’t said how many users installed 1.107.0. Wiz says it has seen stolen AWS credentials being tested; BerriAI hasn’t said whether any stolen credentials have been used. It hasn’t said when regular releases will resume, or which versions are affected by the vulnerability whose disclosure its incident post says is scheduled for October 27.
Sources & method
Sources
- BerriAI/litellm GitHub issue #47826, “[SECURITY] litellm 1.107.0 compromised …” (title shortened), opened Oct 21, 2026, 12:06 UTC, with BerriAI’s replies from Oct 21, 13:50 UTC to Oct 22, 15:54 UTC
- LiteLLM, “Contained: Oct 21, 2026 LiteLLM release v1.107.0 Compromised,” Oct 21, 2026
- LiteLLM, “The attack chain behind the v1.107.0 LiteLLM release,” Oct 23, 2026
- litellm on PyPI
- StepSecurity, “litellm 1.107.0 Compromised on PyPI,” Oct 21, 2026
- Wiz, “LiteLLM Compromised, Steals Credentials,” Oct 21, 2026
- GitHub Changelog, “GitHub CLI: Opt in to expiring, auto-refreshing OAuth tokens,” Oct 21, 2026
Method. Last checked October 24, 2026, at 6:20 a.m. Manila time (22:20 UTC October 23). BerriAI’s statements come from its replies in the GitHub issue, posted by the GitHub account ojensen-berri, whose profile gives the name Oliver Jensen, the title “Director of Security at LiteLLM” and the company BerriAI; GitHub labels the account a contributor to the repository. BerriAI’s October 22, 15:54 UTC reply was posted by the GitHub account krrish-berri-2, whose profile gives the name Krrish Dholakia and the bio “CEO Berri AI”; the incident post lists Krrish Dholakia as CEO of LiteLLM. PyPI’s current state comes from PyPI’s own project data. The payload behavior, affected files and images, remediation steps and the 11:39 and 13:23 UTC times come from the issue’s reporter; the Docker push time, the three-hour window, the mirror warning, the log searches and the March incident come from StepSecurity’s analysis. The attack chain and its starting point come from BerriAI’s October 23 attack-chain post; the exposure windows, affected tags and image digest come from BerriAI’s issue replies and incident post; the post-exploitation activity comes from Wiz; the GitHub CLI token change comes from GitHub’s changelog. We did not download, install or run the affected package or images. The lockfile and CI checks, the agent and gateway credential checks and the cooldown suggestion are our own judgment. No affiliate links on this page. How we work.
Spotted an error? See our corrections policy and tell us.
![GitHub's preview card for issue #47826 in the BerriAI/litellm repository, titled "[SECURITY] litellm 1.107.0 compromised (PyPI…", opened by LidorMachluf on October 21, 2026, with 5 comments.](/images/articles/litellm-1-107-0-pypi-docker-credential-stealer-137eb305.png)


