Skip to content
NewCybercrime Report 2026 · Eight Chapters · A Post Is Not An Incident → Explore The ChaptersCybercrime Report 2026 → Explore

LiteLLM 1.107.0 Release Compromise (October 2026)

On 21 October 2026 a malicious LiteLLM 1.107.0 was published to PyPI and to the project's Docker image tags.

Published
Updated
Reading Time
11 min read
Dark glass parcel box on a conveyor, its lid cracked open and glowing red, cover art for: LiteLLM 1.107.0 release compromise (October 2026)

LiteLLM says its release pipeline was compromised through stolen GitHub CLI OAuth tokens. Its root cause analysis of 23 October traces the start to a master key that was committed to a public repository in May and never revoked. The release carried a credential stealer that runs on every Python start and a loader that runs remote code.

What happened

LiteLLM says its release pipeline was compromised and that version 1.107.0 reached PyPI and Docker registries with malware. The official v1.107.0 source tag on GitHub does not contain the malicious files, according to LiteLLM. On 24 October LiteLLM’s security lead wrote on GitHub issue 47826 that there is in fact no official v1.107.0 source tag. Seven wheels were uploaded to PyPI between 11:39:51 and 11:40:13 UTC, and the Docker image was published at 11:46:56 UTC.

PyPI removed the release at 13:23 UTC, per LiteLLM. LiteLLM says the affected GHCR tags were unavailable by 13:51 UTC and that all affected Docker Hub tags were removed or repointed to clean artifacts by 14:20 UTC. Its enterprise private release was not affected.

Times differ between sources. Wiz writes that the release was quarantined on PyPI “as of 1:20 UTC”. That is before the 11:39 upload, so it most likely means 13:20 UTC.

Wiz also says the images were removed around 13:53 UTC. StepSecurity says BerriAI confirmed the images gone at 14:32 UTC.

We use LiteLLM’s own times above and say where others differ. Our news post has a LiteLLM 1.107.0 response checklist.

LiteLLM’s response: on 21 October 2026 it removed the packages from PyPI, Docker Hub and GHCR and revoked the tokens involved. It removed all but one unaffected user from its GitHub organization.

It also removed trusted publishing links to the organization from public registries. It promised updates every two hours.

PyPI marked release 1.107.0 as quarantined, and the project page shows the badge “Release quarantined on Oct 21, 2026”. SafeDep reports that the account hosting the dead-drop file and its repository were deleted in the afternoon.

Update 23 October 2026: Microsoft Security published its own analysis of the release. It adds that starting Python in an affected environment can be enough to run the stealer and that recovery means rebuilding from verified artifacts, not deleting the litellm folder. See the sections on how it worked and the checks below.

Update 24 October 2026: LiteLLM published its root cause analysis on 23 October at 21:00 UTC. It says the master key of its experimental Agent Platform was committed to the public LiteLLM-Labs/lite-harness repository on 27 May 2026. The commit was force-pushed over, but the key was never revoked.

On 10 October the attacker used that key to read a GitHub organization owner’s GitHub CLI token from the platform. With that token, the attacker took the tokens of two more maintainers from CI secrets. LiteLLM says this replaces its first theory, that the tokens came from the logs of an internal deployment.

Timeline

  1. 27 May 2026, 18:53 UTC

    LiteLLM says a file named opencode.json that holds the master key of its Agent Platform is committed to the public LiteLLM-Labs/lite-harness repository. The commit is later force-pushed over, but the key is not revoked.

  2. 10 Oct 2026, 21:13 to 21:28 UTC

    LiteLLM says the attacker calls the Agent Platform API with the master key; at 21:27 one response returns the GitHub CLI OAuth token of a GitHub organization owner.

  3. 10 Oct 2026, 22:11 UTC

    Socket reports that a workflow named cache.yml, built to collect CI secrets, was committed on a short-lived branch in BerriAI/litellm; a second followed on 12 October. LiteLLM says the run posted six secrets, among them a second maintainer's GitHub token, to a webhook.site endpoint.

  4. 13 Oct 2026, 00:45 UTC

    StepSecurity reports that the domain litellm[.]dev was registered at this time.

  5. 21 Oct 2026, 08:56 to 10:46 UTC

    Wiz and StepSecurity report ten attacker commits pushed to the lookalike repository Berri-AI/litellm.

  6. 21 Oct 2026, 10:08 UTC

    LiteLLM says GitHub branch protection rejected a change to the private release workflow, then a privileged developer credential overrode the protection and applied it.

  7. 21 Oct 2026, 10:46 UTC

    LiteLLM says the modified workflow ran a staging build from the attacker-controlled repository Berri-AI/litellm.

  8. 21 Oct 2026, 11:11 UTC

    LiteLLM says a second developer credential satisfied the production approval gate.

  9. 21 Oct 2026, 11:39 UTC

    Seven malicious litellm 1.107.0 wheels are uploaded to PyPI (11:39:51 to 11:40:13, per LiteLLM).

  10. 21 Oct 2026, 11:46 UTC

    Container publish jobs run and the Docker image contains the malicious content, per LiteLLM.

  11. 21 Oct 2026, 11:53 UTC

    LiteLLM says a third developer credential deleted production and staging workflow records.

  12. 21 Oct 2026, 12:06 UTC

    GitHub issue 47826, reporting the compromise, is opened in the BerriAI/litellm repository; StepSecurity lists the same time.

  13. 21 Oct 2026, 12:09 to 12:24 UTC

    LiteLLM says the attacker pushed a revert of the workflow change and then force-pushed main back, overriding branch protection, so main showed neither commit.

  14. 21 Oct 2026, 13:23 UTC

    PyPI removes litellm 1.107.0, per LiteLLM.

  15. 21 Oct 2026, 13:51 UTC

    Affected GHCR tags are unavailable, per LiteLLM; Docker Hub tags still pointed to the bad image index at that time.

  16. 21 Oct 2026, 14:20 UTC

    All affected Docker Hub tags are removed or repointed to verified clean artifacts, per LiteLLM.

  17. 23 Oct 2026, 21:00 UTC

    LiteLLM publishes its root cause analysis of the attack chain.

How the attack worked

LiteLLM says three engineers’ GitHub accounts were used, through stolen GitHub CLI OAuth tokens. One account changed the release pipeline and triggered the run, another approved it and a third deleted workflow records.

Root cause, per LiteLLM’s analysis of 23 October: on 27 May 2026 a configuration file, opencode.json, was committed to the public LiteLLM-Labs/lite-harness repository. The file held the master key of a LiteLLM Agent Platform deployment, an experimental open source tool that runs cloud agents which open pull requests. LiteLLM says the mistake was caught quickly and the commit was force-pushed over. The exposed keys were marked for revocation, but the master key was never revoked.

The platform held a GitHub CLI OAuth token of a GitHub organization owner. LiteLLM says it was not tied to a service account and not scoped down. On 10 October the attacker used the master key to call the platform API, and one response returned that token.

LiteLLM notes that GitHub CLI tokens are issued after two-factor sign-in, so GitHub’s extra re-authentication step for sensitive actions did not apply. With owner rights the attacker pushed short-lived branches whose workflows posted CI secrets to a webhook.site endpoint, which gave them the tokens of two maintainers. LiteLLM says token hashes in the audit log tie one of them to the approval of the production gate on 21 October. The other matches the deletion of the workflow records.

LiteLLM also says it relaxed a release rule earlier that week. Until then, a special account locked to a device in its office had to approve each release. After the change, any two engineers could start and approve one.

LiteLLM adds that the owner token could have changed that rule too. It believes the attacker used separate tokens to avoid noisy audit logs.

In its incident post of 21 October (update of 20:30 UTC), LiteLLM had suspected that the tokens were taken from the logs of an internal deployment. It now says the request logs show that the first token came from the Agent Platform.

Socket and Wiz add that the build came from a lookalike repository, Berri-AI/litellm, one hyphen away from the real BerriAI/litellm. SafeDep shows that a build setting added a folder named cook to the wheels but not to the source archive. SafeDep rates as moderate to high confidence that the wheels came from attacker-modified source built by the project’s own release pipeline.

The wheels install three files into site-packages: cook.pth, cook.py and sitecustomize.py. The .pth file imports cook at every Python start, using Python Startup Hooks (T1546.018), so no import of litellm is needed. The stealer reads cloud, developer, CI and AI tool credential files and environment variables (Credentials in Files, T1552.001). When a database URL is set, it also reads the LiteLLM proxy tables that hold provider keys.

It encrypts the bundle and posts it to www.litellm[.]dev/healthcheck. The sitecustomize.py file starts a detached loader that checks a GitHub dead-drop file for a domain, then fetches and runs code from it. StepSecurity says the loader fails silently on Windows, while the stealer still runs.

This is a case of Compromise Software Supply Chain (T1195.002). Socket maps it to T1195.001, T1546.018 and T1552.001, among others.

Microsoft says the cook.pth file has a single executable line, import cook, that loads cook.py. That file decodes an embedded collector and runs it in a background thread.

Microsoft says the collector also reads Kubernetes service account files, Docker config and mounted secrets. On Linux, it reads the environment of other readable processes. On the proxy, it reads selected fields from two database tables, up to 500 rows per query.

Microsoft adds that the collector tries to get credentials from the AWS and Google Cloud metadata services. The bundle is encrypted with AES-256-CBC, the key is wrapped with an embedded 4,096-bit RSA public key, and the upload goes to the /healthcheck address.

Microsoft saw a routine Python command that installed an unrelated dependency on Windows start the collector. It maps the case to ATT&CK techniques including T1195.001, T1546.018, T1102.001 and T1105. It says no second-stage retrieval or execution was confirmed, including on the Unix loader path. Microsoft says the dead-drop file was empty when the researchers it cites examined it.

ATT&CK techniques

Who says who was behind it

LiteLLM's own post names no actor. Its root cause analysis of 23 October says the attacker started with a master key that had been committed to a public repository on 27 May and never revoked. CERT-EU reported that the cybercrime actor TeamPCP compromised LiteLLM in March 2026, using the word "reportedly". No source cited on this page links the two events, so we do not.

Microsoft's post of 23 October says it has not independently determined how the developer credentials were first obtained. Socket reports that workflows collecting the project’s CI secrets ran in the BerriAI/litellm repository from at least 10 October 2026. At the time, it said it had not established how the attacker got access.

LiteLLM's analysis links that activity to the release. It says the audit log hash of the GH_TOKEN secret posted on 10 October matches the token that approved the production release on 21 October.

Impact

StepSecurity counts about 49,000 PyPI downloads of 1.107.0 before its removal, a figure that includes CI caches and mirrors and leaves out container pulls. Downloads are not infections. LiteLLM says to assume compromise if 1.107.0 ran in an environment, or if a container ran the affected image digest.

Wiz reports that about 4.5 hours after exfiltration the attacker validated AWS instance role credentials from two IP addresses. The calls were sts:GetCallerIdentity and then Bedrock model listing, which Wiz calls consistent with LLMjacking. Wiz says some environments also saw IAM enumeration.

StepSecurity also says the account that hosted the loader's dead drop has been deleted, but infected hosts keep polling it. See our dead drop explainer and the Dead Drop Resolver technique page.

Lessons

  1. Branch protection can be overridden

    LiteLLM says a privileged credential overrode protection that had just rejected the change. A control that one credential can bypass is a single point of failure.

  2. Approval by credential is not approval by a person

    A second developer credential satisfied the production gate. If tokens are stolen, two approvers can mean two stolen tokens. LiteLLM also says it had relaxed its release approval rule that week, so any two engineers could approve.

  3. A clean source does not mean a clean package

    LiteLLM says the official source was clean while the wheels were not. Compare what you install with the source it claims to come from.

  4. Startup hooks widen the blast radius

    The payload ran whenever Python started, even in programs that never imported litellm, so any script on the host could trigger it.

  5. Removing a package does not undo exposure

    Socket says removing the package does not reverse credential exposure or stop a loader that already runs.

  6. A rewritten commit is still a leaked key

    LiteLLM says the commit with the master key was force-pushed over, but the key was never revoked, and the attacker used it more than four months later. Revoke any secret that was ever public, whatever happens to the commit.

What to check in your own organization

  1. Find the version and the image

    Search lockfiles, caches, build logs and running containers for litellm 1.107.0. Also search for the image digest LiteLLM lists for the affected index: sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339e.

  2. Look for the files

    Search site-packages for litellm-1.107.0.dist-info, cook.pth, cook.py and sitecustomize.py. LiteLLM says finding none does not prove the environment is clean.

  3. Check for the running loader

    Look for a process that holds /tmp/remote_code_loader.lock and end it; StepSecurity puts this step first. Do not run pip install first, because Python startup re-runs the files.

  4. Search network logs

    StepSecurity and Socket list litellm[.]dev, requests to its /healthcheck path and any /codepy request. A /codepy request means second-stage code ran.

  5. Rotate what the host could read

    LiteLLM lists the instance or task role, every provider key in the proxy database, master and virtual keys, the database password and any secret in process environments.

  6. Read the cloud audit log

    LiteLLM says to audit CloudTrail for GetCallerIdentity from the instance role around install time and for use of its credentials from outside your infrastructure.

  7. Compare with Microsoft hashes and hunt

    Microsoft lists SHA-256 hashes for the seven wheels and the startup files. It gives advanced hunting queries for connections to litellm[.]dev, the startup file hashes and OpenSSL commands that use .pc_e_ staging folders. It also says to check uv and pip caches, internal mirrors and lock files, to rebuild from verified artifacts, and to revoke sessions as well as rotate credentials. Microsoft Defender lists four antivirus signatures for this case; the names are in our LiteLLM response checklist post.

  8. Hunt for committed secrets

    Run secret scanning over your public and private repositories, including their history, and revoke every key or token that was ever exposed instead of relying on a rewritten commit. LiteLLM calls this incident an illustration of the risk of not rotating a potentially exposed key. Also give automation narrow tokens: the one that mattered here belonged to an organization owner, not a scoped service account.

Frequently Asked Questions

Which LiteLLM version was malicious?

Only litellm 1.107.0 on PyPI, in all seven wheels, and the Docker tags v1.107.0, latest, main-latest and main-stable. SafeDep lists 1.106.2, 1.107.0rc1 and 1.107.0rc2 as clean.

What is the last safe version?

LiteLLM names litellm 1.106.2, or any explicit version published before the incident. Socket adds that its investigation did not certify every earlier artifact. On 27 October LiteLLM published a separate advisory, GHSA-w4c7-34wj-hqm8, for a critical flaw in proxies run with an Enterprise license. It is fixed in 1.103.10, 1.104.8, 1.105.6 and 1.106.5.

Was I affected if I never imported litellm?

Possibly. SafeDep says the .pth file runs when any Python process starts on the host, even one that never imports litellm.

Is there a CVE for this incident?

No CVE id or GitHub advisory number is cited for it in the sources listed on this page.

Who is behind it?

LiteLLM names no actor, and no source on this page links the October release to a named group.

How is this different from the March 2026 LiteLLM incident?

In March, LiteLLM says versions 1.82.7 and 1.82.8 were uploaded straight to PyPI outside its normal workflow. Both carried a stealer, and 1.82.8 also added a litellm_init.pth file. In October, LiteLLM says its own release pipeline built the bad version from a lookalike repository, and the Docker tags were hit too.

What was the root cause of the October 2026 LiteLLM compromise?

LiteLLM says the master key of its experimental Agent Platform was committed to a public GitHub repository on 27 May 2026 and was never revoked. On 10 October the attacker used it to read a GitHub organization owner's token, then took two maintainers' tokens from CI secrets. On 21 October the owner's token changed the release workflow and started the build, one maintainer's token approved the production release and the other deleted the run records.

Sources

  1. Contained: Oct 21, 2026 LiteLLM release v1.107.0 CompromisedLiteLLM (BerriAI)
  2. The attack chain behind the v1.107.0 LiteLLM releaseLiteLLM (BerriAI)
  3. [SECURITY] litellm 1.107.0 compromised, Issue 47826BerriAI/litellm on GitHub
  4. litellm release history, 1.107.0 quarantinedPython Package Index
  5. Inside the LiteLLM 1.107.0 supply chain compromise: Credential theft through Python startup hooksMicrosoft Security
  6. LiteLLM PyPI Package and Docker Images Compromised to Steal Cloud and AI CredentialsSocket
  7. New Evidence Shows LiteLLM Secret-Stealing Workflows Ran 11 Days Before Supply Chain AttackSocket
  8. LiteLLM Compromised, Steals CredentialsWiz
ShareLinkedInX
Brandefense logo

Stay Ahead of Digital Threats.

Take control of your digital security with an exclusive demo of our AI-driven threat intelligence platform.

Open The Full Demo Form →