LiteLLM attack chain
LiteLLM release-pipeline hijack root cause: unrevoked master key, stolen org-owner tokens, branch-protection override and audit-log-visible cover-up
Posted · Updated · Spectrum Delta Research Team
Summary
LiteLLM's canonical root-cause analysis (Oct 23, B/2 — the vendor's own postmortem, in-window) documents for the first time the intrusion chain behind the already-carded v1.107.0 backdoor: an Agent Platform master key committed to a public repository in May and never revoked let an unidentified attacker extract an organization-owner GitHub CLI OAuth token via the platform API on Oct 10, harvest two maintainer tokens through throwaway-branch CI workflows, and then on Oct 21 disable branch protections, repoint the private release workflow to a lookalike repository, approve the production gate with a stolen token, and delete the workflow-run records and visible history. The whole chain is recorded in GitHub organization audit logs.
Breakdown
Adversary
Unidentified — the primary refers only to 'the threat actor'/'the attacker'
Procedures (3)
Throwaway-branch CI workflows exfiltrate repository secrets
Throwaway-branch workflow runs post repository secrets to an external endpoint
- T1552.001Unsecured Credentials: Credentials In Files
Logs
GitHub organization audit log · protected_branch.destroy; force-pushes; throwaway CI runs; hashed_token- Network / proxy (CI egress) · CI runner POSTs to webhook.site; external secret exfil endpoints
Detectors
No known detector
Click to expand remaining (2) proceduresHide remaining procedures
Branch-protection override repoints the release workflow
Branch-protection destruction and force-push repoint the release workflow to a lookalike source
- T1562.001
Logs
GitHub organization audit log · protected_branch.destroy; force-pushes; throwaway CI runs; hashed_token
Detectors
No known detector
Stolen-token approval, run deletion, history cover-up
Stolen-token production approval, run-record deletion and force-push history cover-up
- T1070Indicator Removal
Logs
GitHub organization audit log · protected_branch.destroy; force-pushes; throwaway CI runs; hashed_token
Detectors
No known detector
Indicators of compromise
Hunt only
(LiteLLM (https://docs.litellm.ai/blog/security-incident-oct-21-2026-attack-chain), B/3) — attacker IPs 69.48.229[.]143 (Oct 10 Agent Platform API access) and 199.91.221[.]39 (Oct 21 project-releaser activity and production-gate approval); secrets posted to an attacker-controlled webhook[.]site endpoint; lookalike repository Berri-AI/litellm at fork commit 20535d8f (served through github.com/BerriAI/litellm/commit/20535d8f); throwaway branches and commits — BerriAI/litellm branch ci-tmp-a351cc commit b69bc36 (posted six secrets incl. GH_TOKEN), BerriAI/litellm-auto branch ci-tmp-be33e9 commit 78d968b (RELEASE_PLEASE_TOKEN), commit 1a6e3c1 (additional repository secrets); release-workflow change commit 9cf97e9 ('ci: release from a fork source repository'), revert 285fbdc5, main force-pushed back to d687b69; stolen credentials: org-owner GitHub CLI OAuth token (held by the Agent Platform, unscoped, not a service account), GH_TOKEN (second maintainer), RELEASE_PLEASE_TOKEN (third maintainer) — identified by audit-log token hash, values not published; discovery via issue #47826 (LidorMachluf). Assessed 2026-10-24, hunt-only — the IPs, branches and webhook endpoint are incident-specific and perishable; the durable hunt value is the audit-log behavior chain: throwaway-branch workflow runs that post secrets externally, branch-protection destruction followed by force-pushes, production approvals by token hashes that match tokens used elsewhere, and workflow-run deletion paired with history force-pushes.
Detailed
Attacker IPs: 69.48.229[.]143 (Oct 10, Agent Platform API access from 21:13-21:28, incl. GET /api/v1/managed_agents/agents?limit=100 at 21:27:10 which returned the org-owner GitHub CLI OAuth token); 199.91.221[.]39 (Oct 21, project-releaser activity and the 11:11:18 production-gate approval). Exfil endpoint: attacker-controlled webhook[.]site. Lookalike: Berri-AI/litellm at fork commit 20535d8f, served via github.com/BerriAI/litellm/commit/20535d8f. Throwaway branches/commits: BerriAI/litellm ci-tmp-a351cc / b69bc36 (22:11:45 run, six secrets incl. GH_TOKEN; run deleted 22:14:14); BerriAI/litellm-auto ci-tmp-be33e9 / 78d968b (22:12:09, RELEASE_PLEASE_TOKEN; run deleted 22:14:31); commit 1a6e3c1 (Oct 12, additional repository secrets, not on the artifact path). Release-workflow change: 9cf97e9 'ci: release from a fork source repository' (rejected 10:08:29 with maintainer token; owner-token override 10:08:34); staging dispatched 10:46:39; production 11:08:53; approval 11:11:18; PyPI wheels published 11:39:51-11:40:13; Docker Hub/GHCR 11:46:56; production run deleted 11:53:49, staging run 11:54:01; revert 285fbdc5 committed 12:09:32, pushed 12:09:38; main force-pushed back to d687b69 at 12:24:52. Stolen credentials: org-owner GitHub CLI OAuth token (unscoped, not a service account, held by the Agent Platform); GH_TOKEN (second maintainer — hash matched the production approval); RELEASE_PLEASE_TOKEN (third maintainer — hash matched the run-record deletions). Discovery: issue #47826 by LidorMachluf at 12:06:41; incident response from 13:02; PyPI quarantine by 13:23; GHCR tags by 13:51; GitHub permissions removed 14:19; Docker Hub tags 14:20. Master key: opencode.json committed to LiteLLM-Labs/lite-harness May 27 18:53:14, force-pushed over, never revoked. All from the primary (LiteLLM (https://docs.litellm.ai/blog/security-incident-oct-21-2026-attack-chain), B/3).
Sources
- B/3LiteLLM: The attack chain behind the v1.107.0 release (primary, canonical root cause)
- A/2GitHub Docs: Audit log events for your organization (telemetry evidence: protected_branch, hashed_token fields)
Grades are source reliability (A–F) and information credibility (1–6).
Questions, detections or sightings of LiteLLM attack chain? Bring them to the community.
Discuss in the Tradecraft Slack