# LiteLLM Supply Chain Compromise (litellm 1.107.0) Targets AI Developer Credentials

> On 2026-10-21 a malicious litellm==1.107.0 was published to PyPI and to GHCR/Docker Hub container tags after the release workflow was pointed at a lookalike 'Berri-AI/litellm' repository. The package drops cook.pth, cook.py and sitecustomize.py, which run at every Python interpreter start, harvest cloud, Kubernetes, SSH, browser, environment and AI-assistant credentials, and exfiltrate them encrypted, while a second loader polls a GitHub dead drop for arbitrary remote Python.

- **Published:** 2026-10-24T00:38:04Z
- **Last reviewed:** 2026-10-24T00:38:04Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-4326
- **ID:** TL-2026-4326
- **Severity:** HIGH
- **Category:** SUPPLY_CHAIN
- **Status:** ACTIVE
- **Detections:** 9 · **IOCs:** 30 (full data via the Threadlinqs MCP server — Purple tier)

## Description

litellm is a widely used Python AI/LLM gateway (Socket reports roughly 23 million weekly downloads before the compromise). On 2026-10-21 seven malicious litellm==1.107.0 wheels (macOS x86_64/arm64, manylinux and musllinux x86_64/aarch64, Windows amd64) were uploaded to PyPI between about 11:39:51 and 11:40:13 UTC, and container images (ghcr.io/berriai/litellm v1.107.0, litellm-database, litellm-non_root, docker.io/litellm/litellm, plus the latest, main-latest and main-stable tags) were published from about 11:46 UTC. Socket's scanner flagged the wheels about seven minutes after publication. PyPI quarantined the release around 13:20 UTC, GHCR images were removed around 13:51-13:53 UTC and Docker Hub tags were repointed to clean images around 14:20 UTC. Wiz reported roughly 49,000 downloads. The last known safe release is 1.106.2.

The attack operated entirely in packaging. Commit 783c43bc (09:48:21 UTC) added data = "cook" to the [tool.maturin] section of pyproject.toml so that a malicious cook/ directory was bundled into the wheel's .data/purelib tree and extracted into the site-packages root. A later commit, 20535d8fa (10:46:29 UTC), added COPY directives to the Dockerfiles. According to StepSecurity, ten commits were pushed to a lookalike repository Berri-AI/litellm (hyphenated, versus the legitimate BerriAI/litellm), stacked on the real v1.107.0 tag; nine were authored by ckdi82fkoos@proton.me and displayed GitHub 'Verified' badges (a web-editor default, not identity proof) and one by Berri-AI@users.noreply.github.com was unsigned. The container build provenance records the release workflow dispatched with source_owner 'Berri-AI', and the lookalike revision matched the PyPI wheel payloads byte for byte. Sources disagree on how the workflow was subverted: StepSecurity reports a stolen organization owner token (bypassing branch protection at 10:08:34 UTC) obtained from GitHub CLI OAuth tokens found in application logs of an internal LiteLLM deployment; Datadog reports stolen GitHub CLI OAuth tokens from three engineers' accounts; Socket and Endor Labs state the authorization mechanism is undetermined from available evidence. Datadog notes this is LiteLLM's second compromise in 2026, with earlier incidents linked to TeamPCP, and that no connection between the campaigns was established.

Three files execute whenever any Python interpreter starts, without litellm ever being imported: cook.pth (executes import cook via the .pth mechanism), cook.py (the 'privcollect' credential stealer, about 61 KB of Base64/zlib-compressed Python, run on a daemon thread, with PRIVCOLLECT_ACTIVE=1 set to suppress re-entry) and sitecustomize.py (a remote code loader with an embedded fallback copy of the stealer). The stealer runs 16 collection modules covering AWS (including IMDSv2 and ECS task credentials), Azure and GCP (including service-account tokens), Kubernetes, Docker, GitHub CLI, Vault, Terraform and CI systems (GitLab Runner, Jenkins), Git/npm/PyPI/.netrc/.env files, SSH and GPG private keys, TLS certificates, Chromium and Firefox login databases, cookies and history, environment variables and /proc/<pid>/environ for all processes, and AI tooling configuration (Codex ~/.codex/auth.json, Claude ~/.claude/.credentials.json, Gemini ~/.gemini/oauth_creds.json, Cursor ~/.cursor/mcp.json, plus Copilot, Windsurf, Kiro, Zed, Continue, OpenCode and Hugging Face). On LiteLLM proxy deployments with DATABASE_URL set it queries the Prisma tables LiteLLM_CredentialsTable and LiteLLM_ProxyModelTable for upstream provider API keys and model configurations.

Data is packed into a tar.gz (hdr.json, data.bin, key.bin), encrypted with a random AES-256-CBC key wrapped with an RSA-4096 OAEP-SHA256 key (public key SHA-256 fingerprint a898fd08ad220fed52488906eb45d196f332b972ad5d85214e7726545ecc4218) and POSTed to http://www.litellm.dev/healthcheck with headers X-SHA256 and X-Token: XWiA8gZNa7NcX2XRoAEb, up to four attempts with a 120-second timeout, using an MSIE 7.0 User-Agent per Aikido. The marker /tmp/.pc_once_72129118c59f5636c0bb is written only after an HTTP 200 response. The loader in sitecustomize.py forks a detached daemon (Linux/macOS; it fails silently on Windows), takes /tmp/remote_code_loader.lock, polls https://raw.githubusercontent.com/letters9813/pythonclient-test/main/domain.txt every 3,600 seconds, extracts a hostname, downloads Python from http://<host>/codepy and runs it with compile()/exec() without any signature or hash verification, giving the operator arbitrary code execution. Earlier dead-drop values localhost:18909 and test.test.com:18909 suggest testing. The dead drop was emptied on 2026-10-20 and again at about 13:01 UTC on 2026-10-21; after disclosure the letters9813 account and repository were deleted. Because the loader persists as a process and the files persist in site-packages, uninstalling litellm does not remove the implant.

Pre-staging: litellm.dev was registered on 2026-10-13 at 00:45 UTC (behind Cloudflare) and the letters9813 GitHub account was created at 06:43 UTC the same day, about a week before the attack. Wiz observed post-exploitation credential validation (sts:GetCallerIdentity followed by Bedrock/LLM API enumeration) from roughly 16:20 to 17:01 UTC on 2026-10-21, about 4.5 hours after exfiltration; Wiz lists IPs 168.100.8.57 and 165.227.201.8 among its network IOCs. Socket noted no confirmed evidence of successful credential theft from individual deployments at the time of its report. No threat actor is attributed in the sources.

## MITRE ATT&CK

- T1583.001 Domains
- T1195.001 Compromise Software Dependencies and Development Tools
- T1078 Valid Accounts
- T1528 Steal Application Access Token
- T1546.018 Python Startup Hooks
- T1059.006 Python
- T1027.013 Encrypted/Encoded File
- T1140 Deobfuscate/Decode Files or Information
- T1552.001 Credentials In Files
- T1552.004 Private Keys
- T1552.005 Cloud Instance Metadata API
- T1555.003 Credentials from Web Browsers
- T1539 Steal Web Session Cookie
- T1082 System Information Discovery
- T1005 Data from Local System
- T1102.001 Dead Drop Resolver
- T1071.001 Web Protocols

## Sources

- [LiteLLM Supply Chain Compromise Exposes AI Developer Credentials to Malware Attacks (GBHackers)](https://gbhackers.com/litellm-supply-chain-compromise/)
- [LiteLLM Supply Chain Attack: Technical Analysis (Socket)](https://socket.dev/blog/litellm-compromise)
- [litellm 1.107.0 Compromised: PyPI Backdoored Wheels Credential Stealer (StepSecurity)](https://www.stepsecurity.io/blog/litellm-1-107-0-compromised-pypi-backdoored-wheels-credential-stealer)
- [LiteLLM compromised on PyPI and Docker (Datadog Security Labs)](https://securitylabs.datadoghq.com/articles/litellm-compromised-pypi-docker/)
- [litellm 1.107.0 Compromised: Python Startup Hooks Steal Cloud, AI and Proxy Credentials (Endor Labs)](https://www.endorlabs.com/learn/litellm-1-107-0-compromised-python-startup-hooks-steal-cloud-ai-and-proxy-credentials)
- [LiteLLM Compromised: Infostealer and RAT (Aikido)](https://www.aikido.dev/blog/litellm-compromised-infostealer-rat)
- [LiteLLM Compromised, Steals Credentials (Wiz)](https://www.wiz.io/blog/litellm-compromised-steals-credentials)

## Full data

Detection queries (Splunk SPL / Microsoft KQL / Sigma) and IOC values require the Threadlinqs MCP server (Purple tier): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-4326
