What Happened
Today on Hacker News: LiteLLM versions 1.82.7 and 1.82.8 on PyPI are compromised.
This is a supply chain attack — malicious code injected into a legitimate package. If you installed these versions, your credentials may be exposed.
This Is Not New
Supply chain attacks happen constantly:
- event-stream (2018) — 2M weekly downloads, maintainer handed off to attacker
- ua-parser-js (2021) — cryptominer injected into 8M weekly download package
- colors + faker (2022) — maintainer self-sabotaged in protest
- LiteLLM (2026) — compromised PyPI release
How to Protect Yourself
Here's a practical detection script using only free APIs:
import requests
import json
def check_pypi_package(name):
"""Detect potential supply chain issues in a PyPI package."""
data = requests.get(f"https://pypi.org/pypi/{name}/json").json()
info = data.get("info", {})
releases = data.get("releases", {})
risks = []
# Check 1: Recent maintainer email change
author_email = info.get("author_email", "")
# Check 2: Very recent release (within hours)
versions = list(releases.keys())
if versions:
latest = versions[-1]
files = releases[latest]
if files:
upload_time = files[0].get("upload_time", "")
print(f"Latest: {latest} uploaded {upload_time}")
# Check 3: Source repo mismatch
project_urls = info.get("project_urls", {}) or {}
home = info.get("home_page", "")
if not home and not project_urls:
risks.append("NO_SOURCE_REPO: no homepage or project URLs")
# Check 4: Yanked versions (often indicates compromise)
yanked = [v for v, files in releases.items()
if any(f.get("yanked", False) for f in files)]
if yanked:
risks.append(f"YANKED_VERSIONS: {yanked}")
# Check 5: Suspiciously few maintainers
maintainer = info.get("maintainer", "")
author = info.get("author", "")
if not maintainer and not author:
risks.append("NO_MAINTAINER_INFO")
return {
"package": name,
"version": info.get("version"),
"risks": risks,
"risk_level": "HIGH" if len(risks) >= 2 else "MEDIUM" if risks else "LOW"
}
# Check your dependencies
for pkg in ["litellm", "requests", "flask", "django"]:
result = check_pypi_package(pkg)
print(f"\n{result['package']}: {result['risk_level']}")
for risk in result["risks"]:
print(f" ⚠️ {risk}")
npm Version (Same Concept)
def check_npm_package(name):
"""Detect supply chain risks in npm packages."""
data = requests.get(f"https://registry.npmjs.org/{name}").json()
versions = list(data.get("versions", {}).keys())
maintainers = data.get("maintainers", [])
risks = []
if len(maintainers) == 1:
risks.append(f"SINGLE_MAINTAINER: {maintainers[0].get('name', 'unknown')}")
# Check for maintainer change in latest version
if len(versions) >= 2:
latest = data["versions"][versions[-1]]
prev = data["versions"][versions[-2]]
if latest.get("_npmUser", {}) != prev.get("_npmUser", {}):
risks.append("PUBLISHER_CHANGED: different user published latest")
# Check GitHub advisories
advisories = requests.get(
f"https://api.github.com/advisories",
params={"ecosystem": "npm", "package": name}
).json()
if isinstance(advisories, list) and advisories:
risks.append(f"KNOWN_CVES: {len(advisories)} advisories")
return {"package": name, "risks": risks}
Prevention Checklist
- ✅ Pin exact versions (
==not>=) - ✅ Use lock files (
poetry.lock,package-lock.json) - ✅ Enable Dependabot or Renovate (free on GitHub)
- ✅ Review changelogs before updating major versions
- ✅ Check maintainer changes on every update
- ✅ Use
pip install --require-hashesin production
Free Tools for Detection
| Tool | What It Checks |
|---|---|
pip audit |
Known CVEs in Python deps |
npm audit |
Known CVEs in Node deps |
| npms.io API | Quality scores |
| GitHub Advisory DB | CVEs by ecosystem |
| Socket.dev | Supply chain analysis |
| PyPI JSON API | Package metadata |
Full scanner: npm-security-scanner
Python tools: python-security-tools
How do you protect against supply chain attacks? Share your workflow 👇
Top comments (0)