AISLE Found Compromised LiteLLM Package 3 Minutes After Release

See what AISLE can find and fix autonomously in your own code.
AISLE’s dependency firewall caught a credential stealer with persistence in the wheels of LiteLLM, the popular Python package, just 3 minutes and 14 seconds after it was released.
Our AI found no issues in LiteLLM source code. Rather, all 7 wheels (download artifacts) of LiteLLM 1.107.0 on PyPI contained malware.
Timeline (UTC)
Time | Event |
|---|---|
11:39:51 | First 1.107.0 file (macOS x86_64 wheel) uploaded to PyPI |
11:40:13 | Last file (sdist) uploaded; 8 files total |
11:43:05 | AISLE's dependency firewall flags the first wheel |
12:00:06 | All 7 wheels flagged |
afterwards | Manual analysis confirms the malware; all 7 wheels blocked |
follow-up | PyPI quarantines the release |
From upload to first detection: 3 min 14 s.
Technical Details
A wheel can contain a <name>.data/purelib/ directory. pip copies everything in that directory straight into site-packages, next to all your other packages, not inside the litellm/ folder. The attacker used this to drop three extra files:
JavaScript1litellm-1.107.0.data/purelib/cook.pth2litellm-1.107.0.data/purelib/cook.py3litellm-1.107.0.data/purelib/sitecustomize.py
Python runs both kinds of file automatically:
.pthfiles insite-packagesare processed every time Python starts. A line that starts withimportis executed.cook.pthcontains onlyimport cook.sitecustomize.pyis imported automatically every time Python starts.
So the malware runs on every Python start on that machine, even if your code never imports litellm. Removing litellm with pip later does not clean this up unless pip also removes the extra files.
Stage 1: credential stealer (cook.py)
cook.py is one line: Python source compressed with zlib, base64-encoded, then passed to exec. Decoded, it is about 60 KB of credential-stealing code organised into modules:
- System and network info
- Browser saved passwords and history (Chrome, Edge, Brave, Firefox, …), including code to decrypt Chrome's stored passwords
- SSH keys, GPG keys, TLS private keys
- Shell history
- Cloud credentials (AWS, GCP, Azure, …) and cloud instance metadata (
169.254.169.254) - Kubernetes service-account tokens and container credentials
- CI/CD secrets and developer tool secrets
- AI developer tool config
- All environment variables
- litellm's own database config
It packs the data into a tar archive, encrypts it with AES plus an embedded RSA public key, and POSTs it to:
JavaScript1http://www.litellm.dev/healthcheck
litellm.dev is a lookalike domain. The real project uses litellm.ai. The request carries the header X-Token: XWiA8gZNa7NcX2XRoAEb and an old Internet Explorer User-Agent string. A marker file at /tmp/.pc_once_72129118c59f5636c0bb keeps it from running twice.
Stage 2: remote code loader (sitecustomize.py)
sitecustomize.py contains the same stealer, plus a loader that:
- Forks into a background process detached from the terminal. It uses
/tmp/remote_code_loader.lockso only one copy runs. - Every hour, downloads a domain name from
https://raw.githubusercontent.com/letters9813/pythonclient-test/main/domain.txt - Downloads
http://<that domain>/codepyand runs it withexec.
When we looked, domain.txt was empty, so the loader had nothing to fetch yet. But the attacker can turn it on at any time by editing one file on GitHub. Every infected machine would then run whatever code they publish. The GitHub repository was created on 18 October, three days before the release.
How did it get onto PyPI?
The source on GitHub looks clean:
- The
v1.107.0tag onBerriAI/litellmpoints to an ordinary, signed commit. - The sdist (
litellm-1.107.0.tar.gz) does not contain the malicious files. - The previous wheels (1.106.1, 1.106.2) do not contain them either.
Only the built wheels were changed. That points to a compromised build or publish step, or a stolen PyPI publishing token, not to malicious code in the repository. This is a breaking story; we have not yet confirmed which.
[Update] PyPI quarantines the release
Shortly after our report, PyPI maintainers reached out to let us know they had quarantined the release:

Our thanks to them for responding so quickly.
What you should do
If you installed litellm 1.107.0 from a wheel:
- Treat the machine as compromised.
- Check
site-packagesforcook.pth,cook.pyandsitecustomize.py, and/tmpfor the marker and lock files below. Kill any background Python process that holds/tmp/remote_code_loader.lock. - Rotate every credential the machine could see: cloud keys, SSH keys, CI/CD secrets, API keys in environment variables, browser-saved passwords, Kubernetes tokens.
- Pin litellm to 1.106.2 or a later release that is confirmed clean.
Indicators of compromise
Network
http://www.litellm.dev/healthcheck(exfiltration; behind Cloudflare: 104.26.10.8, 104.26.11.8, 172.67.73.104)https://raw.githubusercontent.com/letters9813/pythonclient-test/main/domain.txt(stage-2 config)- HTTP header
X-Token: XWiA8gZNa7NcX2XRoAEb
Files
site-packages/cook.pth,site-packages/cook.py,site-packages/sitecustomize.py/tmp/.pc_once_72129118c59f5636c0bb/tmp/remote_code_loader.lock
Malicious wheels (sha256)
Wheel | sha256 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The sdist (2befe2a79fb4fbbd9a543b5b40b530c8cffa8771bab22b8fb22b2e4ae3b1f819) does not contain the malicious files.
Our peers at Upwind were the first to publicly report this issue. Stay tuned here for more details.


.webp&w=3840&q=75)






