LiteLLM describes the full attack chain: a leaked master key, an unscoped token, and relaxed approvals
LiteLLM published a revised root cause for the attack on its release pipeline on October 24: a master key for Agent Platform was accidentally committed to a public GitHub repo on May 27, 2026, and was never revoked. According to the company, this was the key that gave the attacker the way in to poison version 1.107.0 of the popular Python package on October 21 — a reconstruction that differs from the company's earlier pointer to leaked Claude Code logs, with the two explanations left unreconciled. For users still cleaning up, the corrected chain does not change what they need to do, but it shows which three control failures made the attack possible.
The beginning: a key published in May, never revoked
LiteLLM's Oliver Jensen and Mateo Wang describe in the updated investigation how a configuration file was committed to the public repository LiteLLM-Labs/lite-harness on May 27, 2026. The file contained the master key for a deployment of LiteLLM Agent Platform, a tool the company uses to orchestrate agents.
The mistake was quickly spotted, and the commit was force-pushed away. According to Jensen and Wang, they themselves identified the exposed keys as needing revocation — but the revocation was never carried out for the master key. This is the company's own account, as reported by The Hacker News (The Hacker News, quotes translated from English).
So in May, the company noticed the problem. For more than four months, the key sat available to anyone who had copied it from the repo history.
October 10: owner-level access and tokens stolen from CI
According to LiteLLM, an unknown attacker, operating from IP address 69.48.229[.]143, used the unrevoked key on October 10, 2026 to gain access to Agent Platform. There, the attacker extracted a GitHub CLI OAuth token that the platform was configured with to let self-hosted cloud agents open pull requests against GitHub repositories. The token was, according to the company, not scoped down, and was tied to the company's GitHub account for the organization owner.
That same evening, between 22:11 and 22:12 UTC, the attacker committed malicious workflows to the repositories BerriAI/litellm and BerriAI/litellm-auto, according to the timeline. The goal was to capture the GitHub CLI OAuth tokens associated with two engineers with maintainer rights, by sending them to an attacker-controlled endpoint on webhook[.]site. Both runs were deleted within minutes.
Socket has dug out two malicious commits that added a workflow at .github/workflows/cache.yml, on October 10 and 12. Security researcher Karlo Zanki of Socket explains that neither commit was pushed to a branch that still exists, but to short-lived branches named ci-tmp- that were "created, used, and deleted within minutes," and that this is why the activity "leaves almost nothing behind in the repository's ordinary history" (The Hacker News, quotes translated from English).
This explains why the attack was not visible in ordinary repo history: it took place on branches that never survived.
October 21: relaxed approvals, one hyphen, and three hours on PyPI
The stolen tokens lay dormant until October 21. Between 10:08 and 11:08 UTC, according to LiteLLM's timeline, branch protection was overridden, and the release pipeline was pointed at a doppelgänger repository: "Berri-AI/litellm" with a hyphen, instead of the real "BerriAI/litellm". One misplaced hyphen separated the malicious source repository from the legitimate one.
Here the third control failure comes into play. LiteLLM explains that releases normally require that an authorized engineer starts the build, and that it is approved by "a special account locked to a physical device in our office". According to the company, this rule had been relaxed earlier that week, to accommodate a temporary push for more frequent releases and backports, so that any two engineers could start and approve a release. The attacker thus used, according to LiteLLM, one of the tokens to start the release, after pointing the deployer at its malicious repository, and another to approve it (The Hacker News, quotes translated from English).
Version 1.107.0 was published to PyPI on October 21 between 11:39 and 11:40 UTC, and to Docker Hub and GHCR at 11:46. Upwind researcher Lidor Machluf reported the malicious package at 12:06. PyPI quarantined the version at 13:23, while Docker, according to Help Net Security, continued serving the malicious build until 14:20 (Help Net Security).
Over the roughly three hours the packages were available, they were downloaded more than 49,000 times, according to SecurityWeek citing estimates from LiteLLM and ClickPy (SecurityWeek). For a library that Socket estimates has around 23 million downloads per week, and that typically runs with vendor API keys, cloud identities, and database connection strings nearby, that is a significant exposure (Help Net Security).
What the malware actually did
According to Wiz, the package contained compiled malware with a dual function: a credential stealer and a remote access tool. Wiz researchers Benjamin Read and Rami McCarthy describe a persistence technique they had not seen documented in the wild before: the malware used both .pth files (cook.pth/cook.py, which exfiltrated data to litellm[.]dev/healthcheck) and sitecustomize.py (which fetched a C2 domain from a GitHub dead drop) at the same time.
"The approach of two techniques, using both .pth files and sitecustomize.py simultaneously, appears to be the first documented case in the wild," Read and McCarthy write (translated from English) (The Hacker News).
Wiz has also seen the stolen credentials in use. About four and a half hours after the data left the victims' systems, the attacker began validating AWS credentials harvested from compromised CI runners and Kubernetes nodes, and checked whether they could reach AI models on Amazon Bedrock — activity Wiz links to LLMjacking, that is, abuse of stolen cloud credentials to run AI workloads on the victim's bill (Help Net Security).
Wiz states that the last clean version was 1.106.2. LiteLLM says that customers using the company's private repository for enterprise releases were not affected (SecurityWeek).
The revision: two explanations left unreconciled
The new account differs substantially from the company's original report after October 21. At that time, LiteLLM wrote that they believed the attacker had gained access to an internal deployment exposed to the internet, harvested GitHub CLI OAuth tokens from Claude Code responses logged there, and used those credentials to compromise the release workflow (TNW). According to that report, the attack involved three developers' credentials: one to turn off branch protection, one to approve the release, and one to delete traces.
The updated version places the entry point at the unrevoked master key and token theft via CI workflows. The sources in this record do not reconcile the two explanations, and it is unclear whether the master key explanation is meant to replace or supplement the Claude Code theory — for example, how the attacker initially reached the internal deployment was previously unconfirmed. Readers should therefore treat both descriptions as the company's own, partly unresolved reconstructions, not as documented fact.
Three control failures — and what users still need to do
The practical lesson lies in the three failures LiteLLM itself names in its reconstruction:
- Leaked keys must actually be revoked. The company identified the master key as needing revocation in May — and never carried it out. Force-pushing a commit away does not remove the key from everyone who has already copied it.
- Token scope matters. A GitHub CLI OAuth token that was not scoped down, and that was tied to the organization owner account, gave the attacker a path onward to the repositories.
- Temporary relaxation of release controls is an attack window. The rule of one authorized trigger and one device-locked approver was replaced with any two engineers being able to start and approve releases — precisely the week the attacker struck.
For users, the advice is unchanged by the revised root cause: Check whether you installed 1.107.0, and treat any installations of that version as compromised. Rotate all credentials that may have been exposed, including AWS keys from CI environments. Wiz gives 1.106.2 as the last clean version.
Several questions remain open: It is not known how many victim environments were actually compromised, or whether an additional stage of the malware was delivered via the GitHub dead-drop channel. No one has attributed the attack to an actor, and Socket has, according to The Hacker News, found no evidence linking the attack to LiteLLM's compromise in March — whether such a link exists is therefore an open question (The Hacker News).

