Skip to content

How to Check If Your Python Project Was Exposed to LiteLLM Malware: A Complete Security Audit Guide

Problem

When I checked my project’s dependencies today, I saw this terrifying news:

SECURITY ALERT: LiteLLM versions 1.82.7 and 1.82.8 on PyPI contained
credential-stealing malware. These versions were downloaded 47,000 times
in just 46 minutes before being removed.

The problem is that LiteLLM is a popular library for LLM API calls, and it might be installed in my projects directly or as a transitive dependency. I had no idea if my credentials were compromised.

Environment

  • Python 3.10+
  • pip 23.0+
  • Various projects using LiteLLM for LLM integration
  • CI/CD pipelines that might have installed during the vulnerability window
  • API keys for OpenAI, Anthropic, and other LLM providers

What Happened?

On March 27, 2026, malicious versions of LiteLLM (1.82.7 and 1.82.8) were uploaded to PyPI. Within just 46 minutes, these packages were downloaded 47,000 times before being discovered and removed.

I tried to understand what made these versions dangerous:

check-version.sh
# Check if litellm is installed
pip show litellm
# Output if vulnerable:
# Name: litellm
# Version: 1.82.7 <-- MALICIOUS!
# or
# Version: 1.82.8 <-- MALICIOUS!

But the problem goes deeper. LiteLLM could be installed as a dependency of other packages, and I might not even know it’s there.

Step 1: Check Direct Dependencies

I started by searching all my dependency files:

search-deps.sh
# Search all common dependency files
grep -r "litellm" requirements.txt Pipfile poetry.lock pyproject.toml setup.py setup.cfg
# Common vulnerable patterns:
# litellm==1.82.7 -- VULNERABLE (exact match)
# litellm==1.82.8 -- VULNERABLE (exact match)
# litellm>=1.82.0 -- POTENTIALLY VULNERABLE (could resolve to 1.82.7/8)
# litellm>=1.82.6 -- POTENTIALLY VULNERABLE (could resolve to 1.82.7/8)

In my case, I found this in one project:

requirements.txt
litellm>=1.82.0,<1.83.0

This version range could have resolved to the malicious versions during the attack window.

Step 2: Audit Transitive Dependencies

I realized I needed to check if other packages depend on LiteLLM:

check-transitive.sh
# Install pipdeptree if not already installed
pip install pipdeptree
# Check the dependency tree
pipdeptree | grep -A 5 -B 5 litellm
# Output example showing litellm as a dependency:
# langchain-community==0.3.0
# ├── litellm==1.82.7 <-- VULNERABLE!
# └── pydantic==2.5.0

I also checked what’s actually installed in my virtual environment:

check-installed.sh
# Show installed version
pip show litellm
# Or use pip list
pip list | grep litellm
# Check installation date
pip show litellm | grep "Location:"
# Then check the file timestamp in that directory

The critical question: When was it installed?

check-timestamp.sh
# Find when litellm was installed
ls -la $(python -c "import litellm; import os; print(os.path.dirname(litellm.__file__))")
# Check the site-packages directory timestamp
stat $(python -c "import site; print(site.getsitepackages()[0])")

Step 3: Check CI/CD Build Logs

I realized my CI/CD pipelines might have installed during the vulnerability window. I checked the build logs:

check-ci-logs.sh
# Example: Check GitHub Actions logs for pip install timestamps
# The vulnerability window was approximately:
# March 27, 2026, during the 46-minute period when 1.82.7/8 were live
# If using GitHub Actions, check workflow run times:
gh run list --repo myorg/myrepo --workflow build.yml --limit 50
# Look for pip install or requirements installation steps
# around the vulnerability timestamp

For Docker images, I checked when they were built:

check-docker.sh
# List Docker images with creation dates
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.CreatedAt}}"
# If you find images built during the vulnerability window,
# check what packages are inside:
docker run --rm myimage:tag pip list | grep litellm

Step 4: Automated Vulnerability Scanning

I tried using automated tools to scan for vulnerabilities:

scan-vulns.sh
# Install security scanning tools
pip install pip-audit safety
# Method 1: pip-audit scans installed packages
pip-audit
# Output if vulnerable:
# Name Version ID Description
# litellm 1.82.7 PYSEC-2026-XXX Credential stealing malware
# litellm 1.82.8 PYSEC-2026-XXX Credential stealing malware
# Method 2: pip-audit can scan requirements files
pip-audit -r requirements.txt
# Method 3: Safety checks against vulnerability database
safety check -r requirements.txt
# Output:
# +==============================================================================+
# | REPORT |
# | reported by safety |
# +==============================================================================+
# | litellm version 1.82.7 found |
# | CVE-2026-XXXX: Credential stealing malware detected in setup.py |
# +==============================================================================+

Step 5: Credential Rotation

After confirming potential exposure, I immediately rotated all credentials:

rotate-creds.sh
# First, check what credentials might have been exposed
env | grep -i key
env | grep -i token
env | grep -i secret
env | grep -i api
# Common credentials to rotate:
# - OpenAI API keys (sk-...)
# - Anthropic API keys (sk-ant-...)
# - AWS credentials (AKIA...)
# - GitHub tokens (ghp_..., gho_...)
# - Any service tokens used in CI/CD

I created a checklist for credential rotation:

rotation-checklist.txt
[ ] OpenAI API keys - https://platform.openai.com/api-keys
[ ] Anthropic API keys - https://console.anthropic.com/
[ ] AWS credentials - IAM console
[ ] GitHub personal access tokens - Settings > Developer settings
[ ] CI/CD secrets (GitHub Actions, GitLab CI, etc.)
[ ] Environment variables in production
[ ] Docker registry credentials
[ ] Any LLM provider keys used with LiteLLM

Step 6: Implement Protective Measures

To prevent future attacks, I implemented several protective measures:

6.1 Pin Dependencies with Hashes

requirements.txt with hashes
# requirements.txt with hash verification
litellm==1.82.6 \
--hash=sha256:abc123... \
--hash=sha256:def456...
# This prevents installation if the hash doesn't match
pip install --require-hashes -r requirements.txt

6.2 Use Private PyPI Mirror with Lead Time

pip.conf
# ~/.config/pip/pip.conf (Linux/Mac)
# or %APPDATA%\pip\pip.ini (Windows)
[global]
index-url = https://your-private-mirror.com/simple/
# Configure lead time to delay new package versions
# This gives time for security issues to be discovered

6.3 Implement Dependency Scanning in CI/CD

.github/workflows/security.yml
name: Security Scan
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: pip install pip-audit safety
- name: Run pip-audit
run: pip-audit -r requirements.txt
- name: Run safety check
run: safety check -r requirements.txt
- name: Check for specific vulnerable packages
run: |
pip install litellm==1.82.6 # Safe version
if pip show litellm | grep -E "Version: 1.82.[78]"; then
echo "ERROR: Vulnerable LiteLLM version detected"
exit 1
fi

6.4 Version Pinning Strategy

requirements-pinned.txt
# BAD: Allows any version (including malicious ones)
litellm>=1.82.0
# GOOD: Pins to specific safe version
litellm==1.82.6
# BETTER: Upper bound constraint
litellm>=1.82.6,<1.83.0
# BEST: Exact version with hash
litellm==1.82.6 \
--hash=sha256:abc123...

How to Verify Your System is Clean

I created a verification script:

verify-clean.sh
#!/bin/bash
echo "=== LiteLLM Malware Verification Script ==="
# Check 1: Direct dependencies
echo ""
echo "Checking direct dependencies..."
if grep -rE "litellm.*(1\.82\.7|1\.82\.8)" requirements.txt Pipfile pyproject.toml setup.py 2>/dev/null; then
echo "ERROR: Vulnerable LiteLLM version found in dependencies"
exit 1
else
echo "OK: No vulnerable versions in direct dependencies"
fi
# Check 2: Installed packages
echo ""
echo "Checking installed packages..."
INSTALLED_VERSION=$(pip show litellm 2>/dev/null | grep "Version:" | cut -d' ' -f2)
if [ "$INSTALLED_VERSION" = "1.82.7" ] || [ "$INSTALLED_VERSION" = "1.82.8" ]; then
echo "ERROR: Vulnerable LiteLLM version $INSTALLED_VERSION is installed"
exit 1
else
echo "OK: LiteLLM version $INSTALLED_VERSION is safe"
fi
# Check 3: Transitive dependencies
echo ""
echo "Checking transitive dependencies..."
if pipdeptree 2>/dev/null | grep -E "litellm.*(1\.82\.7|1\.82\.8)"; then
echo "ERROR: Vulnerable LiteLLM found as transitive dependency"
exit 1
else
echo "OK: No vulnerable transitive dependencies"
fi
# Check 4: Run pip-audit
echo ""
echo "Running pip-audit..."
if ! pip-audit 2>/dev/null; then
echo "WARNING: pip-audit found vulnerabilities"
fi
# Check 5: Run safety
echo ""
echo "Running safety check..."
if ! safety check 2>/dev/null; then
echo "WARNING: safety found vulnerabilities"
fi
echo ""
echo "=== Verification Complete ==="

The Reason

I think the key reasons why this attack was so impactful:

1. Speed of Attack - 47,000 downloads in 46 minutes means automated CI/CD pipelines were hit hard. Many developers never knew they were exposed.

2. Trusted Package - LiteLLM is a legitimate, popular package for LLM integration. It’s not a typosquatting attack; the actual package was compromised.

3. Transitive Dependencies - Many projects don’t even know they depend on LiteLLM because it’s pulled in through other packages.

4. CI/CD Blind Spots - Build pipelines automatically install dependencies without human oversight, making them prime targets for supply chain attacks.

5. Credential Exposure - The malware specifically targeted credentials (API keys, tokens, secrets), which are often stored in environment variables accessible to Python processes.

Common Mistakes

I noticed several mistakes developers make when responding to this attack:

Mistake 1: Only checking direct dependencies

Terminal window
# WRONG: Only checks requirements.txt
cat requirements.txt | grep litellm
# RIGHT: Check all dependency sources
grep -rE "litellm" requirements.txt Pipfile poetry.lock pyproject.toml
pipdeptree | grep litellm

Mistake 2: Assuming version ranges are safe

# DANGEROUS: This could have installed 1.82.7/8 during the attack window
litellm>=1.82.0
# SAFE: Explicitly exclude vulnerable versions
litellm>=1.82.0,!=1.82.7,!=1.82.8

Mistake 3: Not checking CI/CD history

Terminal window
# Check when your CI/CD pipelines built during the attack window
# GitHub Actions example:
gh run list --workflow build.yml --created "2026-03-27"
# GitLab CI example:
# Check pipeline history in GitLab UI for March 27, 2026

Mistake 4: Delaying credential rotation

If there’s any chance of exposure, rotate immediately. Don’t wait for confirmation - by the time you confirm, attackers may have already used your credentials.

Mistake 5: Not implementing preventive measures

After cleaning up, many developers go back to their old practices. Implement:

  • Private PyPI mirrors with lead time
  • Dependency pinning with hash verification
  • Automated security scanning in CI/CD
  • Regular credential rotation schedules

Summary

In this post, I showed how to check if your Python project was exposed to the LiteLLM malware attack. The key points are:

  1. Check direct dependencies in requirements.txt, Pipfile, poetry.lock, and pyproject.toml for versions 1.82.7 and 1.82.8

  2. Audit transitive dependencies using pipdeptree to find hidden LiteLLM installations

  3. Verify CI/CD history to see if builds occurred during the 46-minute vulnerability window

  4. Rotate all credentials immediately if there’s any chance of exposure

  5. Implement preventive measures like private PyPI mirrors, hash verification, and automated security scanning

The LiteLLM incident demonstrates that supply chain attacks can happen to any package, even trusted ones. By conducting thorough security audits and implementing defensive measures, you can protect your projects from similar attacks in the future.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments