Trojanized LiteLLM 1.107.0 Package Steals Credentials Through Python Startup Hooks

Summary
A trojanized LiteLLM 1.107.0 package and Docker images stole credentials via Python startup hooks. The stealer targeted cloud, browser, AI and other secrets; the malicious release and images were removed, and involved tokens revoked.
Key points
- The malicious LiteLLM 1.107.0 package was uploaded to PyPI on October 21; trojanized Docker images also carried it. PyPI quarantined the package, and the affected image tags were removed.
- The attacker reportedly used stolen GitHub CLI OAuth tokens from three engineers’ accounts to push malicious commits and trigger and approve the release. BerriAI said the involved tokens were revoked.
- The package used cook.pth to load cook.py at Python interpreter startup; a second startup script, sitecustomize.py, attempted to retrieve a follow-on payload through a GitHub-hosted dead drop.
- The stealer collected browser, cloud, SSH, GPG, shell-history and AI-provider credentials, and queried LiteLLM Proxy’s PostgreSQL credentials table.
- Harvested data was encrypted and sent to an attacker-controlled lookalike domain, litellm[.]dev. The article says the second-stage domain file had not been populated beyond test values at analysis time.
- The article identifies 1.106.2 as the latest safe version and provides hashes for affected package wheels and container images.
Article Details
- Attack Vectors
- A malicious LiteLLM 1.107.0 package was uploaded to PyPI and included in LiteLLM Docker images; startup-executed cook.pth and sitecustomize.py files enabled credential theft and loader behavior.
- The attacker reportedly used stolen GitHub CLI OAuth tokens to access engineers' GitHub accounts, push malicious commits, and trigger and approve the project release.
- The stealer harvested browser credentials and cookies, cloud credentials and tokens, AI-provider API keys, SSH and GPG keys, shell history, and credentials stored in the LiteLLM Proxy PostgreSQL database.
- Stolen data was encrypted and sent by HTTP POST to an attacker-controlled lookalike LiteLLM domain. A separate sitecustomize.py loader attempted to retrieve a second-stage script via a GitHub dead-drop file.
- Defensive Notes
- The malicious 1.107.0 package was quarantined on PyPI; the article identifies 1.106.2 as the most recent safe version.
- The trojanized Docker tags v1.107.0, latest, main-latest, and main-stable were removed, and the GitHub repository used for the dead drop was taken down.
- LiteLLM's developer reported that all tokens involved in the attack had been revoked.
- Review the article's SHA-256 indicators for affected package wheels and container images, and its listed hashes for cook.pth, cook.py, and sitecustomize.py.
Indicators of compromise
| Type | Indicator | Context |
|---|---|---|
| DOMAIN | litellm[.]dev | Attacker-controlled lookalike domain identified as exfiltration infrastructure. |
ckdi82fkoos@proton[.]me | Author email used for the attacker's malicious commits. | |
| SHA256 | 03ac2a8b752605d1d7710979c17ff18b03dd978203ba23ba97fd8ce3d6f897ea | Hash of the Windows cook.py credential-stealer payload. |
| SHA256 | 0aaf7ba346d41ef2f40390436738b001180d5a1c03aa093f121078a9969d9a1a | Hash of the malicious LiteLLM 1.107.0 macOS arm64 wheel. |
| SHA256 | 12d4ccc5c6f8d35cf4f2cf233b7f3e418e863e657d81ff5f5fc9e210005b9484 | Hash of the malicious LiteLLM 1.107.0 Windows wheel. |
| SHA256 | 1bbce8caa94f01c0aaa0b7ddae51553a8a32e1ce53d96d44fe583272aff7ad00 | Hash of the malicious LiteLLM 1.107.0 musllinux x86_64 wheel. |
| SHA256 | 24581ddc30767f16ecb69d2b0517556f2cd7dea56971adb42a3d1beb97d69523 | Hash of the trojanized LiteLLM database container image for linux/amd64. |
| SHA256 | 34bef04fe88ac9d0aae0475630b1738681d15b94f233ac8aa46eacf5968305fa | Hash of the Linux/macOS sitecustomize.py loader. |
| SHA256 | 462d0c9f67ca522d9e0e4acd245e90b36ce0d5353604a66bb7c43a1ec4a6fcf7 | Hash of the malicious LiteLLM 1.107.0 manylinux x86_64 wheel. |
| SHA256 | 56b74573eed6e4aafe4b50603dbe7853e0345f188c8e44a09f1098caf1f4bcdf | Hash of the trojanized LiteLLM 1.107.0 GHCR and Docker Hub linux/arm64 image. |
| SHA256 | 645a67d810628252d63df85dcc8824c58bcc77cf8383f4d3e6321f0ccc3ce9e4 | Hash of the trojanized LiteLLM non-root container image for linux/amd64. |
| SHA256 | 668169d35b87bf51324080390b1b1c5ab12bd335cfe5f1a99e3689abd5e02ae6 | Hash of the malicious LiteLLM 1.107.0 manylinux aarch64 wheel. |
| SHA256 | 7598727f209d717041db37f7dca271d3a7d328a279890e0e1d55375729aeb86d | Hash of the malicious LiteLLM 1.107.0 macOS x86_64 wheel. |
| SHA256 | 7f191632e7320705d154b85204f1ae546b543acbd7e8861229b76f5042b92bdb | Hash of the cook.pth persistence hook for Linux and macOS. |
| SHA256 | 827dd893c74cf621a860a66a3a447a5c732533f087589ce905573e285c0a239c | Hash of the trojanized LiteLLM database container image for linux/arm64. |
| SHA256 | 84dc8c82c0a4a4a62552ef826b49fcc86d1a5c4a5d0f2c06665723f93d129d7d | Hash of the cook.pth persistence hook for Windows. |
| SHA256 | 9dd0a3926f96a37eb86cf1ee2310d9be93139cc4ebef3ef9e2efe9531390be25 | Hash of the Linux/macOS cook.py credential-stealer payload. |
| SHA256 | b6122440d0d9cb1eb1ade9933f49214da8c31288de7710c076c2680dfa528465 | Hash of the Windows sitecustomize.py loader. |
| SHA256 | bd1aeee419ea36da9aa2b657288da4101887be468f020ac63d22ba6ed84a3ea5 | Hash of the trojanized LiteLLM 1.107.0 GHCR and Docker Hub linux/amd64 image. |
| SHA256 | c2e32d0ce2548aa662c18bf5001911a79fe5b30cf8357132275add02fdcde054 | Hash of the malicious LiteLLM 1.107.0 musllinux aarch64 wheel. |
| SHA256 | f75c8edae59b72b1ebfd617295833f465c85bb2fab9c1d60f21b496db86cb8da | Hash of the trojanized LiteLLM non-root container image for linux/arm64. |
MITRE ATT&CK
T1005 · Data from Local SystemThe stealer gathered local files including cloud and AI configuration data, keys, and shell history.T1027 · Obfuscated Files or Informationcook.py deobfuscated itself before running its credential-stealing routine.T1041 · Exfiltration Over C2 ChannelThe malware sent encrypted stolen data to its attacker-controlled endpoint.T1059.006 · PythonPython startup files cook.pth and sitecustomize.py caused malicious Python code to execute when an interpreter started.T1071.001 · Web ProtocolsStolen data was exfiltrated over HTTP POST to the attacker-controlled healthcheck endpoint.T1102.001 · Dead Drop Resolversitecustomize.py attempted to retrieve domain.txt from a GitHub repository used as a dead drop.T1105 · Ingress Tool TransferThe loader attempted to download and run a second-stage Python script from the domain specified by the dead-drop file.T1195.002 · Compromise Software Supply ChainThe attacker inserted malicious files into the LiteLLM release pipeline and distributed them through the PyPI package and Docker images.T1528 · Steal Application Access TokenThe stealer targeted Azure CLI cached tokens.T1550.001 · Application Access TokenAccording to LiteLLM's developer, the attacker appeared to use stolen GitHub CLI OAuth tokens to operate through engineers' GitHub accounts.T1552.001 · Credentials In FilesThe stealer searched ~/.aws/ and environment variables for AWS credentials.T1552.004 · Private KeysThe stealer collected SSH private keys and GPG keys.T1552.006 · Group Policy PreferencesThe stealer queried EC2/ECS instance metadata for credentials.T1555 · Credentials from Password StoresThe stealer collected credentials and cookies from Chrome, Firefox, Edge, and Safari.T1555.003 · Credentials from Web BrowsersThe payload targeted browser credentials and cookies stored by Chrome, Firefox, Edge, and Safari.
Malware
Vendors
Products
DockerLiteLLM Docker containers on GHCR and Docker hub also included the trojanized version of LiteLLM. These included the v1.107.0 , latest, main-latest and main-stable tags. These were removed ~13:53 UTC.GHCRLiteLLM Docker containers on GHCR and Docker hub also included the trojanized version of LiteLLM. These included the v1.107.0 , latest, main-latest and main-stable tags. These were removed ~13:53 UTC.GitHubmalicious actions were taken through three engineers' GitHub accounts, appearing to be by way of stolen GitHub CLI OAuth tokens. The threat actor used one user's account triggered the project-releaser run, and anotherLiteLLMLiteLLM CompromisedPyPIAt 11:39 UTC on October 21, a malicious version (1.107.0) of the LiteLLM package was uploaded to PyPI. This version was quarantined on PyPI as of 1:20 UTC.