The LiteLLM project — one of the most widely deployed open-source LLM proxy/gateway libraries, used to normalize API calls across OpenAI, Anthropic, Azure, Bedrock, and dozens of other model providers — has suffered a supply-chain compromise. Attackers gained access to the project's release pipeline and published a trojanized package to PyPI along with malicious Docker images. The injected payload is an info-stealer purpose-built for this target: it harvests credentials, secrets, and environment variables from affected systems.
If that blast radius sounds enormous, it is. LiteLLM's entire job is to sit at the center of your AI infrastructure holding API keys. The typical LiteLLM deployment runs with environment variables containing OPENAI_API_KEY, ANTHROPIC_API_KEY, AZURE_API_KEY, AWS credentials for Bedrock, database connection strings for its proxy state, and often cloud IAM credentials inherited from the host or container role. A stealer that dumps os.environ from inside a LiteLLM process is, in effect, a skeleton key for your entire AI and cloud estate.
Every organization that installed or upgraded LiteLLM — via pip install litellm, a pinned requirements file, or the official Docker images (ghcr.io/berriai/litellm / Docker Hub) — during the compromise window must treat this as an active incident, not a patching exercise.
Technical Analysis
What Was Compromised
Based on reporting by BleepingComputer and the project's response:
- Attack vector: The attackers compromised the project's release pipeline — the CI/CD mechanism that publishes artifacts. This is the critical distinction. This was not a typo-squatted lookalike package; the malicious code shipped through the legitimate distribution channels (PyPI and container registries) under the real project name. That defeats the most common supply-chain hygiene advice ("only install the official package") because the official package itself was poisoned.
- Affected artifacts: Malicious releases published to PyPI under the
litellmpackage name, and malicious Docker images pushed to the project's official container repositories. Because the compromise window and exact version list are still being finalized by the maintainers, defenders should pull the authoritative list of bad versions/tags from the LiteLLM GitHub security advisory rather than rely on secondary reporting. - Payload behavior: An info-stealer that enumerates and exfiltrates credentials, secrets, and environment variables. In a LiteLLM context that means LLM provider API keys, proxy master keys (
LITELLM_MASTER_KEY), database URLs (DATABASE_URL), and any cloud credentials present in the process environment or accessible via the container's metadata service.
Why This Attack Chain Is So Effective
From a defender's perspective, this incident follows the modern supply-chain playbook we've now seen across npm, PyPI, and container registries:
- Pipeline compromise, not code compromise. The attacker doesn't need to land a malicious PR past code review. By hijacking the credentials or CI system that publishes releases, they inject the payload at build/publish time. Source repositories can look clean while shipped artifacts are malicious.
- The target is a credential concentrator. LiteLLM is architecturally designed to hold secrets for every model provider an organization uses. One compromised container yields dozens of high-value keys.
- Egress blends in. A LiteLLM proxy's normal job is making outbound HTTPS calls to API endpoints. Stealer exfiltration over HTTPS from inside a LiteLLM container hides in an enormous volume of expected outbound traffic.
- Docker distribution multiplies reach. Many teams deploy LiteLLM via
docker pullwithlatestor floating tags — meaning the malicious image could be running in production Kubernetes clusters without any developer ever runningpip install.
Exploitation Status
This is confirmed, active, in-the-wild malicious distribution — not a theoretical vulnerability. Any environment that pulled affected artifacts executed the stealer code on container/package start. There is no CVE assigned to this incident as of publication (supply-chain compromises of this type rarely receive CVEs; the identifier that matters is the set of malicious package versions and image digests, which the maintainers are publishing via their GitHub advisory).
Detection & Response
The detections below target the behaviors inherent to this stealer: environment/secret enumeration, suspicious child processes from the LiteLLM runtime, and anomalous egress from LiteLLM workloads. They are deliberately scoped to the LiteLLM process context to keep fidelity high — a broad "any process reading environment variables" rule would be disabled within a week, and rightfully so.
Sigma Rules
---
title: LiteLLM Process Spawning Shell or Reconnaissance Tools
id: 3f8a2c1e-7b4d-4e9a-b1c6-2d5e8f0a9b3c
status: experimental
description: Detects the LiteLLM Python runtime spawning shells, curl/wget, or environment-dumping utilities — consistent with the injected info-stealer payload executing from within the compromised package.
references:
- https://www.bleepingcomputer.com/news/security/litellm-release-pipeline-hacked-to-distribute-info-stealer-malware/
- https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/03/24
tags:
- attack.execution
- attack.t1059.006
- attack.t1195.002
logsource:
category: process_creation
product: linux
detection:
selection_parent:
ParentCommandLine|contains:
- 'litellm'
- 'uvicorn'
- 'gunicorn'
selection_child:
CommandLine|contains:
- '/bin/sh'
- '/bin/bash'
- 'curl '
- 'wget '
- 'printenv'
- ' env'
- '/proc/self/environ'
- 'base64'
condition: selection_parent and selection_child
falsepositives:
- Health-check scripts or entrypoint wrappers legitimately launched by the container entrypoint — tune per image
level: high
---
title: Process Reading Linux Environment Block of Other Processes
id: 9c1d4e7a-2f5b-4a8c-9d3e-6b0f1a2c4d5e
status: experimental
description: Detects reads against /proc/<pid>/environ, a common technique for harvesting environment variables and secrets from running processes such as an LLM proxy.
references:
- https://www.bleepingcomputer.com/news/security/litellm-release-pipeline-hacked-to-distribute-info-stealer-malware/
- https://attack.mitre.org/techniques/T1552/
author: Security Arsenal
date: 2026/03/24
tags:
- attack.credential_access
- attack.t1552.001
logsource:
category: process_creation
product: linux
detection:
selection:
CommandLine|contains:
- '/proc/'
- 'environ'
filter_legit:
CommandLine|contains:
- 'pm2'
- 'datadog-agent'
- 'containerd'
- 'kubelet'
condition: selection and not filter_legit
falsepositives:
- Container runtimes, APM agents, and process supervisors inspecting their children
level: medium
---
title: Base64-Encoded Outbound Data Transfer From Python Runtime
id: 5e2b7d9f-1a3c-4b6e-8f2a-7c9d0e1b3a4f
status: experimental
description: Detects Python processes piping data through base64 encoding to curl/wget — a common exfiltration pattern for harvested environment variables and secrets in containerized workloads.
references:
- https://attack.mitre.org/techniques/T1041/
- https://attack.mitre.org/techniques/T1132.001/
author: Security Arsenal
date: 2026/03/24
tags:
- attack.exfiltration
- attack.t1041
- attack.t1132.001
logsource:
category: process_creation
product: linux
detection:
selection_pipe:
CommandLine|contains:
- 'base64'
selection_exfil:
CommandLine|contains:
- 'curl'
- 'wget'
- 'nc '
- '/dev/tcp/'
selection_parent:
ParentImage|endswith:
- '/python'
- '/python3'
condition: selection_pipe and selection_exfil and selection_parent
falsepositives:
- Build scripts and CI jobs running inside Python-based containers
level: high
KQL — Microsoft Sentinel / Defender
This hunt assumes Linux container hosts ship Syslog/auditd via the AMA agent, and that Defender for Endpoint (or Defender for Containers) covers your Kubernetes nodes. It looks for secret-enumeration and exfiltration behaviors parented by the LiteLLM runtime, plus anomalous egress from LiteLLM pods.
// Hunt 1: Suspicious child processes spawned by LiteLLM / Python runtimes
let litellm_parents = dynamic(["litellm", "uvicorn", "gunicorn", "python", "python3"]);
let suspicious_children = dynamic(["curl", "wget", "sh", "bash", "base64", "nc", "ncat", "printenv", "env"]);
union isfuzzy=true (DeviceProcessEvents, (Syslog | where Facility == "auth" or Type == "EXECVE"))
| extend Proc = tostring(coalesce(FileName, ProcessName)),
CmdLine = tostring(coalesce(ProcessCommandLine, CommandLine)),
ParentProc = tostring(coalesce(InitiatingProcessFileName, ""))
| where ParentProc has_any (litellm_parents) or CmdLine has_any ("litellm")
| where Proc in~ (suspicious_children)
or CmdLine has_any ("/proc/self/environ", "/proc/1/environ", "printenv", "os.environ")
| summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), Commands=make_set(CmdLine, 20) by DeviceName, ParentProc, Proc
| order by FirstSeen desc;
// Hunt 2: Outbound connections from LiteLLM workloads to non-LLM destinations
// Baseline your expected providers (api.openai.com, api.anthropic.com, *.amazonaws.com, etc.) — anything else is suspect.
let expected_llm_destinations = dynamic(["api.openai.com", "api.anthropic.com", "generativelanguage.googleapis.com", "amazonaws.com", "openai.azure.com", "cohere.ai", "api.mistral.ai"]);
DeviceNetworkEvents
| where InitiatingProcessCommandLine has_any ("litellm", "uvicorn", "gunicorn")
or InitiatingProcessFileName has_any ("python", "python3")
| where RemoteUrl !has_any (expected_llm_destinations)
and RemoteIPType == "Public"
| summarize Connections=count(), RemoteIPs=make_set(RemoteIP, 25), RemoteURLs=make_set(RemoteUrl, 25)
by DeviceName, InitiatingProcessFileName, bin(TimeGenerated, 1h)
| order by Connections desc;
Velociraptor VQL
For rapid fleet-wide triage — especially on bare-metal or VM-based LiteLLM deployments where you need to identify who is running the package and what it's talking to — this artifact enumerates LiteLLM processes, their network connections, and recently modified package files inside site-packages (post-install hooks and stealer implants leave fresh timestamps).
-- LiteLLM compromise triage: running processes, egress, and recent package modifications
LET proc_hunt = SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE CommandLine =~ 'litellm|uvicorn|gunicorn'
OR Exe =~ 'python'
LET net_hunt = SELECT Pid, Name, Status, Laddr, Raddr
FROM netstat()
WHERE Status =~ 'ESTABLISHED'
LET pkg_hunt = SELECT FullPath, Mtime, Size
FROM glob(globs=['/usr/lib/python3*/site-packages/litellm/**',
'/usr/local/lib/python3*/site-packages/litellm/**',
'/opt/**/site-packages/litellm/**',
'/home/*/.local/lib/python3*/site-packages/litellm/**'])
WHERE Mtime > now() - 86400 * 7
SELECT * FROM proc_hunt
UNION ALL
SELECT Pid, NULL AS Ppid, Name, Laddr.String AS CommandLine, Raddr.String AS Exe, NULL, NULL FROM net_hunt
Remediation & Verification Script
Run this on any Linux host or container that may have installed LiteLLM during the compromise window. It inventories installed versions, checks for telltale stealer artifacts, and flags unexpected egress. Cross-reference the reported versions against the official LiteLLM GitHub security advisory — do not rely on the version list in this script being complete.
#!/usr/bin/env bash
# LiteLLM supply-chain compromise triage — run on hosts/containers that pulled litellm
set -u
echo "=== [1] Installed litellm versions across pip environments ==="
for py in python3 python; do
command -v "$py" >/dev/null 2>&1 && "$py" -m pip show litellm 2>/dev/null | grep -E '^(Name|Version|Location)'
done
find / -name "METADATA" -path "*litellm*dist-info*" 2>/dev/null | while read -r f; do
echo "--- $f"; grep -E '^Version:' "$f"
done
echo "=== [2] Running litellm / proxy processes ==="
ps auxww | grep -Ei 'litellm|uvicorn|gunicorn' | grep -v grep
echo "=== [3] Established outbound connections from python processes ==="
ss -tnp 2>/dev/null | grep -i python
echo "=== [4] Suspicious post-install artifacts in site-packages ==="
find / -path "*site-packages/litellm*" -name "*.pth" 2>/dev/null
find / -path "*site-packages/litellm*" -newermt "2026-03-01" -type f 2>/dev/null | head -50
echo "=== [5] Environment exfil traces in shell histories ==="
grep -rEh 'environ|printenv|/proc/self/environ' /root/.bash_history /home/*/.bash_history 2>/dev/null
echo "=== [6] Docker images pulled from LiteLLM registries ==="
if command -v docker >/dev/null 2>&1; then
docker images --digests | grep -Ei 'litellm|berriai'
echo "--- Inspect digests: compare against known-good digests in the LiteLLM advisory"
fi
echo ""
echo "NEXT STEPS: If any litellm install falls in the compromise window:"
echo " 1. Isolate the host/pod from the network (do NOT just delete the container — preserve for forensics)."
echo " 2. Rotate ALL secrets present in that environment: LLM API keys, LITELLM_MASTER_KEY, DATABASE_URL, cloud creds."
echo " 3. Review cloud audit logs (CloudTrail, Azure Activity Log, GCP Audit) for key misuse since the install date."
Remediation
Treat every potentially affected deployment as a confirmed credential exposure until proven otherwise. Priority order:
- Identify exposure immediately. Inventory every location LiteLLM is installed: pip environments (dev laptops, notebooks, CI runners, application servers), container images (
ghcr.io/berriai/litellm, Docker Hub), Kubernetes deployments, and any internal images builtFROMa LiteLLM base. Check pull/install timestamps against the compromise window in the BleepingComputer report and the official LiteLLM GitHub security advisory, which carries the authoritative list of malicious versions and image digests. - Pin to a known-clean version and verify integrity. Upgrade/downgrade to a maintainer-confirmed clean release. Go further: pin by hash (
pip install --require-hashes) and by image digest (image: ghcr.io/berriai/litellm@sha256:...) rather than mutable tags. Eliminatelatestand floating version ranges (>=,*) for LiteLLM everywhere — this incident is exactly what floating tags cost you. - Rotate every secret the environment could see. This is non-negotiable and it is the most labor-intensive step: all LLM provider API keys,
LITELLM_MASTER_KEYand virtual keys,DATABASE_URL/ Postgres credentials, Redis credentials, cloud IAM keys and instance-role-derived credentials, SMTP/Slack webhook secrets, and anything else in the container's env. Invalidate sessions/tokens derived from those secrets too. - Hunt for post-exploitation use of stolen keys. Pull provider usage logs (OpenAI/Anthropic usage dashboards, Azure OpenAI diagnostic logs) and cloud audit trails (CloudTrail, Azure Activity Log, GCP Audit Logs) covering the period from installation to credential rotation. Look for API calls from unexpected source IPs, regions, or user agents; new IAM principals; and anomalous Bedrock/model invocations. Stolen LLM keys are monetized fast — expect resale and abuse within days.
- Rebuild, don't patch, containers. Destroy affected containers/pods and redeploy from a verified-clean image. Preserve a snapshot or memory capture of at least one affected instance for forensics before teardown if you suspect data beyond env vars was staged.
- Harden the pipeline side going forward. This compromise succeeded at the release layer. As consumers you can't fix LiteLLM's CI, but you can insulate yourself: run a private artifact proxy (Artifactory/Nexus/devpi) with a quarantine-and-scan gate before new versions reach production; enable dependency firewalling to block packages published within the last N days (a 7–14 day cooling-off window defeats most pipeline hijacks, which are detected quickly); and require Sigstore/cosign verification for container images where available.
- Segment and constrain egress. A LiteLLM proxy has a small, enumerable set of legitimate destinations (the LLM provider APIs). Enforce egress allowlisting at the namespace/host firewall so the workload cannot reach arbitrary internet endpoints. This single control would have neutralized the exfiltration phase entirely.
If you confirm execution of a malicious artifact in a production environment, escalate to a formal incident response process — credential theft at this scope has downstream obligations (contractual, and potentially regulatory where the proxy handled regulated data in prompts).
Related Resources
Security Arsenal Incident Response Services AlertMonitor Platform Book a SOC Assessment incident-response Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.