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 containedcredential-stealing malware. These versions were downloaded 47,000 timesin 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 if litellm is installedpip 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 all common dependency filesgrep -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:
litellm>=1.82.0,<1.83.0This 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:
# Install pipdeptree if not already installedpip install pipdeptree
# Check the dependency treepipdeptree | 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.0I also checked what’s actually installed in my virtual environment:
# Show installed versionpip show litellm
# Or use pip listpip list | grep litellm
# Check installation datepip show litellm | grep "Location:"# Then check the file timestamp in that directoryThe critical question: When was it installed?
# Find when litellm was installedls -la $(python -c "import litellm; import os; print(os.path.dirname(litellm.__file__))")
# Check the site-packages directory timestampstat $(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:
# 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 timestampFor Docker images, I checked when they were built:
# List Docker images with creation datesdocker 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 litellmStep 4: Automated Vulnerability Scanning
I tried using automated tools to scan for vulnerabilities:
# Install security scanning toolspip install pip-audit safety
# Method 1: pip-audit scans installed packagespip-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 filespip-audit -r requirements.txt
# Method 3: Safety checks against vulnerability databasesafety 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:
# First, check what credentials might have been exposedenv | grep -i keyenv | grep -i tokenenv | grep -i secretenv | 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/CDI created a checklist for credential rotation:
[ ] 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 LiteLLMStep 6: Implement Protective Measures
To prevent future attacks, I implemented several protective measures:
6.1 Pin Dependencies with Hashes
# requirements.txt with hash verificationlitellm==1.82.6 \ --hash=sha256:abc123... \ --hash=sha256:def456...
# This prevents installation if the hash doesn't matchpip install --require-hashes -r requirements.txt6.2 Use Private PyPI Mirror with Lead Time
# ~/.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 discovered6.3 Implement Dependency Scanning in CI/CD
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 fi6.4 Version Pinning Strategy
# BAD: Allows any version (including malicious ones)litellm>=1.82.0
# GOOD: Pins to specific safe versionlitellm==1.82.6
# BETTER: Upper bound constraintlitellm>=1.82.6,<1.83.0
# BEST: Exact version with hashlitellm==1.82.6 \ --hash=sha256:abc123...How to Verify Your System is Clean
I created a verification script:
#!/bin/bash
echo "=== LiteLLM Malware Verification Script ==="
# Check 1: Direct dependenciesecho ""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 1else echo "OK: No vulnerable versions in direct dependencies"fi
# Check 2: Installed packagesecho ""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 1else echo "OK: LiteLLM version $INSTALLED_VERSION is safe"fi
# Check 3: Transitive dependenciesecho ""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 1else echo "OK: No vulnerable transitive dependencies"fi
# Check 4: Run pip-auditecho ""echo "Running pip-audit..."if ! pip-audit 2>/dev/null; then echo "WARNING: pip-audit found vulnerabilities"fi
# Check 5: Run safetyecho ""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
# WRONG: Only checks requirements.txtcat requirements.txt | grep litellm
# RIGHT: Check all dependency sourcesgrep -rE "litellm" requirements.txt Pipfile poetry.lock pyproject.tomlpipdeptree | grep litellmMistake 2: Assuming version ranges are safe
# DANGEROUS: This could have installed 1.82.7/8 during the attack windowlitellm>=1.82.0
# SAFE: Explicitly exclude vulnerable versionslitellm>=1.82.0,!=1.82.7,!=1.82.8Mistake 3: Not checking CI/CD history
# 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, 2026Mistake 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:
-
Check direct dependencies in requirements.txt, Pipfile, poetry.lock, and pyproject.toml for versions 1.82.7 and 1.82.8
-
Audit transitive dependencies using pipdeptree to find hidden LiteLLM installations
-
Verify CI/CD history to see if builds occurred during the 46-minute vulnerability window
-
Rotate all credentials immediately if there’s any chance of exposure
-
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:
- 👨💻 PyPI Security Best Practices
- 👨💻 pip-audit Documentation
- 👨💻 Safety CLI Documentation
- 👨💻 LiteLLM Official Repository
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments