
LiteLLM Supply Chain Incident Response: Removing the cook.pth Backdoor and Hardening AI Gateways on Linux
Run a routine container rebuild or dependency update for your LiteLLM AI gateway proxy, and your server silently starts exfiltrating production API keys before your first test request even executes. On October 21, 2026, threat actors compromised LiteLLM release credentials and published a malicious v1.107.0 release to PyPI and container registries. Instead of relying on application-level execution, the payload injected dropped scripts directly into Python root site-packages directories.
The breach happens instantly.
When an infected Python interpreter boots, standard startup routines evaluate .pth files and run initialization scripts prior to executing user code. Teams running automated CI/CD runners or production proxies using :latest container tags had their cloud tokens, master gateway secrets, and upstream LLM keys harvested without raising a single application exception.
This incident response guide provides exact Linux detection commands for the cook.pth backdoor, details safe cleanup procedures that prevent re-executing malicious payloads, and outlines defense-in-depth configurations for AI gateway infrastructure.
Anatomy of the Incident: Why Standard Uninstalls Fail
The compromised litellm==1.107.0 wheel packaged a directory named cook/ containing three critical payload files: cook.pth, cook.py, and sitecustomize.py. The setup script dropped these files directly into the root site-packages directory of the host Python environment.
In standard Python environments, the site module processes all .pth lines during interpreter initialization. When a .pth file contains executable statements starting with import, the interpreter executes those statements immediately. Furthermore, Python automatically loads sitecustomize.py if present in sys.path.
Host Boot Sequence Under Infection:
1. python3 invocation begins (e.g., systemd service, docker entrypoint, or pip)
2. Python interpreter initializes core runtime
3. site.py scans /usr/local/lib/python3.XX/site-packages
4. cook.pth executes -> triggers cook.py payload
5. sitecustomize.py loads -> activates credential harvester
6. Upstream LLM keys (OpenAI, Anthropic, Gemini, AWS) read from memory and env
7. LiteLLM_CredentialsTable queried in PostgreSQL database
8. Encrypted payload exfiltrated to command-and-control endpoint
9. Target application (or pip command) finally begins execution
Do not run pip uninstall litellm in an infected environment.
Because invoking pip executes the Python interpreter, running an uninstaller re-triggers the malicious credential scraper and remote execution loader. Remediating this breach requires raw filesystem operations and complete container destruction.
Step 1: Detect Indicators of Compromise (IOCs) on Linux
Log into your gateway hosts, Kubernetes worker nodes, and CI/CD runner instances. Run the following shell command to scan all local Python installations and virtual environments for the dropped artifacts:
# Scan system libraries and user virtual environments for IOC files
find / -name "cook.pth" -o -name "cook.py" -o -name "sitecustomize.py" 2>/dev/null
If the scan returns files matching cook.pth or suspicious sitecustomize.py entries outside standard OS packages, inspect the directory structure immediately:
# Check contents of candidate site-packages directory
ls -la /home/user/app-env/lib/python3.11/site-packages/cook*
Verify whether network sockets opened connections to unauthorized external hosts:
# Inspect current established TCP connections from Python processes
sudo ss -tupn | grep python
The malware also establishes an hourly polling task. Check system crontabs and systemd timers:
# Check crontabs for anomalous automated curl or python scripts
sudo crontab -l
cat /etc/crontab
ls -la /etc/cron.*
Step 2: Safe Teardown Without Interpreter Re-Execution
If an environment contains cook.pth, treat the entire host or container as fully compromised. Do not attempt in-place package patching.
Scenario A: Linux Virtual Environments
Purge the entire virtual environment directory using standard filesystem deletion tools rather than Python package managers:
# Stop any running gateway daemon immediately
sudo systemctl stop litellm-proxy
# Destroy the infected virtual environment directory completely
rm -rf /home/user/app-env
# Recreate a clean virtual environment from scratch
python3.11 -m venv /home/user/app-env
source /home/user/app-env/bin/activate
Scenario B: Docker and Containerized Deployments
Docker containers that pulled tags litellm/litellm:latest, main-latest, or main-stable during the incident window must be destroyed and untagged:
# Stop and remove infected container instances
docker stop litellm-proxy
docker rm litellm-proxy
# Remove the cached infected image from local Docker storage
docker rmi litellm/litellm:latest litellm/litellm:main-latest litellm/litellm:v1.107.0 2>/dev/null
# Prune build cache to eliminate contaminated wheel layers
docker builder prune -a -f
Step 3: Pinned Installation and Cryptographic Verification
Never deploy production AI gateways using mutable :latest tags or unpinned package specifications. To safely deploy LiteLLM on Linux, pin your installation to a verified clean version such as v1.106.2 (or verified clean patch v1.107.1+).
Requirements Manifest with Hash Enforcement
Enforce strict hash checking in your requirements.txt to block poisoned wheels even if upstream package repositories experience unauthorized overwrites:
# requirements.txt - Verified clean installation
litellm==1.106.2 \
--hash=sha256:4a79b0c26889c0a6b7e617d3d5f5e27a696cb8a48e7152064de2d0ec72f094eb
Install using the hash-checking flag:
pip install --require-hashes -r requirements.txt
Immutable Container Digest Pinning
When running LiteLLM Proxy via Docker or Kubernetes, reference the immutable image digest rather than semantic version tags:
# docker-compose.yml
services:
litellm:
# Pin explicitly to the verified immutable SHA256 digest
image: ghcr.io/berriai/litellm@sha256:7e068ff66e51240c5fbf972ba7e16345e69dd1c1092ca9720b0800dc01b7a67e
container_name: litellm-proxy
restart: always
ports:
- "127.0.0.1:4000:4000"
environment:
- DATABASE_URL=postgresql://proxy_user:proxy_pass@postgres:5432/litellm_db
- LITELLM_MASTER_KEY=sk-master-replacement-token-2026
volumes:
- ./config.yaml:/app/config.yaml:ro
read_only: true
user: "1000:1000"
tmpfs:
- /tmp:rw,noexec,nosuid,size=64m
Notice the security flags in the deployment definition:
read_only: true: Locks the container root filesystem. Even if a malicious package attempts to write.pthfiles intosite-packages, the kernel returnsRead-only file systemand blocks the write.user: "1000:1000": Runs the daemon without root capabilities.tmpfs /tmp:noexec: Prevents execution of downloaded second-stage binaries in temporary folders.
Step 4: Credential Revocation and Database Hygiene
Because the malicious payload explicitly queried LiteLLM_CredentialsTable and scraped process environment variables, you must assume all upstream credentials stored or routed through an infected host are compromised.
Execute this rotation checklist immediately:
- Master Gateway Key: Generate a new
LITELLM_MASTER_KEYand distribute it to downstream client agents. - Upstream LLM Provider Tokens: Revoke and re-issue API keys across OpenAI, Anthropic, Google Gemini, DeepSeek, and Mistral.
- Database Passwords: Update the PostgreSQL or SQLite authentication passwords connecting to the LiteLLM metadata store.
- Cloud Infrastructure Secrets: Rotate AWS IAM access keys, Azure service principal credentials, and Google Cloud service account JSON keys resident on the host.
Inspect the PostgreSQL database for unexpected administrative users or modified routing configurations:
-- Connect to the LiteLLM backend database
\c litellm_db
-- Review stored credentials table for unauthorized additions
SELECT key_name, spend, max_budget FROM "LiteLLM_VerificationToken";
-- Verify user table entries
SELECT user_id, user_email, user_role FROM "LiteLLM_UserTable";
Step 5: Egress Firewall Lockdown on Linux
Production AI gateways require outbound network access to reach LLM inference endpoints. However, they should never initiate outbound connections to arbitrary remote IP addresses or external code repositories.
Configure iptables or ufw to restrict egress traffic to authorized API endpoints and DNS servers:
# Allow loopback and established return traffic
sudo iptables -A OUTPUT -o lo -j ACCEPT
sudo iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Allow outbound DNS resolution
sudo iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
sudo iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
# Allow outbound HTTPS traffic to upstream AI providers
sudo iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT
# Log and drop all other outbound traffic from the proxy host
sudo iptables -A OUTPUT -j LOG --log-prefix "[LITELLM-EGRESS-DROP]: "
sudo iptables -A OUTPUT -j DROP
Egress filtering stops exfiltration. When a compromised container attempts to telephone home to an attacker IP address over non-standard ports or unapproved protocols, kernel packet filtering terminates the connection before data escapes your network perimeter.
Primary Documentation & Advisory References
- LiteLLM Official GitHub Repository: Upstream releases, security advisories, and architecture documentation.
- Python Official site Module Specification: Detailed documentation regarding
.pthfile processing andsitecustomizeexecution mechanics. - Docker Container Security Best Practices: Hardening Linux containers using read-only filesystems, dropped capabilities, and non-root execution.
- NIST Software Supply Chain Guidelines: Standard procedures for integrity verification and dependency hash enforcement.