Skip to main content

Supply chain compromise scanner — detects known PyPI and npm attacks via data-driven threat profiles

Project description

Supply Chain Compromise Scanner

A data-driven scanner that detects indicators of compromise (IOCs) from known PyPI and npm supply chain attacks. Threat profiles are defined in TOML files and are user-extensible — add your own without writing code.

Built-in threat profiles:

ID Package Ecosystem Compromised Versions Date
litellm-2026-03 litellm PyPI 1.82.7, 1.82.8 2026-03-24
axios-2026-03 axios npm 1.14.1, 0.30.4 2026-03-31

No guarantees. This tool attempts to find known artifacts associated with supply chain compromises. It does not guarantee detection of all malicious activity, nor does it guarantee that a clean scan means your system was not affected. A determined attacker may have removed traces, and the tool cannot detect secrets that have already been exfiltrated. Use this scanner as one input in your incident response — not as a definitive verdict.

Quick Start

Option A: Install from PyPI

Linux / macOS:

# Recommended — installs in an isolated environment
pipx install scan-litellm-compromise
scan-litellm

If you don't have pipx: sudo apt install pipx (Debian/Ubuntu) or brew install pipx (macOS).

Alternatively, using pip inside a virtual environment:

python3 -m venv /tmp/scanner && /tmp/scanner/bin/pip install scan-litellm-compromise
/tmp/scanner/bin/scan-litellm

Note: pip install directly will fail on modern Linux distributions (Debian 12+, Ubuntu 23.04+, Fedora 38+) due to PEP 668. Use pipx or a virtual environment instead.

Windows:

pip install scan-litellm-compromise
scan-litellm

Or using a virtual environment:

py -m venv %TEMP%\scanner && %TEMP%\scanner\Scripts\pip install scan-litellm-compromise
%TEMP%\scanner\Scripts\scan-litellm

Option B: Run from source (no install needed)

Linux / macOS:

git clone https://github.com/CognitiveSand/scan_litellm_compromise.git
cd scan_litellm_compromise
python3 run_scan.py

Windows — double-click run_scan.bat, or from a terminal:

git clone https://github.com/CognitiveSand/scan_litellm_compromise.git
cd scan_litellm_compromise
py run_scan.py

No dependencies required — uses only the Python 3.11+ standard library.

Command-Line Options

Flag Description
(no flags) Scans all known threats (default behavior).
--threat ID Scan for a specific threat only (e.g. --threat litellm-2026-03).
--threat-file PATH Load a custom threat profile from a TOML file.
--list-threats List all available threat profiles and exit.
--scan-path DIR Restrict scanning to a specific directory instead of system-wide search.
--resolve-c2 Enable live DNS queries to C2 domains (default: use known IPs only).
--help Show usage information.

Warning about --resolve-c2: This flag causes the scanner to make live DNS queries to attacker-controlled domains. This carries real risks:

  • Operational security: Your DNS query is visible to the attacker's infrastructure.
  • Network monitoring: The queries may trigger alerts in your SIEM/IDS.

In most cases you do not need this flag. The scanner ships hardcoded known IPs confirmed by multiple threat intelligence sources.

Examples:

# Scan for all known threats (default)
scan-litellm

# Scan only a specific project directory
scan-litellm --scan-path /home/user/myproject

# Scan for a specific threat only
scan-litellm --threat axios-2026-03

# List available threat profiles
scan-litellm --list-threats

# Use a custom threat profile
scan-litellm --threat-file ./my-threat.toml

Threat Library

Threat profiles are TOML files that define everything about a specific supply chain attack: package name, ecosystem, compromised versions, C2 infrastructure, IOC file paths, and remediation steps.

Built-in threats

Ship with the package in scan_litellm_compromise/threats/. Updated via pip install --upgrade.

User-defined threats

Drop a .toml file into:

  • Linux/macOS: ~/.config/scan-supply-chain/threats/
  • Windows: %LOCALAPPDATA%\scan-supply-chain\threats\

User profiles override built-in profiles with the same id.

Writing a threat profile

[threat]
id          = "mypackage-2026-04"
name        = "MyPackage Supply Chain Attack"
date        = "2026-04-01"
ecosystem   = "pypi"          # "pypi" or "npm"
package     = "mypackage"
compromised = ["1.0.1"]
safe        = "1.0.0"
advisory    = "https://example.com/advisory"
description = "Description of what happened."

[c2]
domains = ["evil.example.com"]
ports   = []

[c2.ips]
"evil.example.com" = ["1.2.3.4"]

[[ioc.known_paths]]
description = "backdoor payload"
linux       = ["/tmp/backdoor.py"]
darwin      = ["/tmp/backdoor.py"]
windows     = ['%TEMP%\backdoor.exe']

[ioc.phantom_deps]
names = ["malicious-dep"]       # should NEVER exist

[ioc.kubernetes]
pod_patterns = []
namespace    = ""

[ioc.windows]
registry_keywords = []
schtask_keywords  = []

[remediation]
rotate_secrets  = true
install_command = "pip install mypackage==1.0.0"

[remediation.remove_artifacts]
linux   = ["Remove /tmp/backdoor.py"]
darwin  = ["Remove /tmp/backdoor.py"]
windows = ['Remove %TEMP%\backdoor.exe']

[remediation.check_persistence]
linux   = ["Check crontab -l"]
darwin  = ["Check launchctl list"]
windows = ["Check Task Scheduler"]

Video Overview

This scanner was inspired by Fahd Mirza's video highlighting the LiteLLM incident — thanks to him for bringing it to attention.

Known Attacks

LiteLLM PyPI Compromise (March 24, 2026)

Two backdoored versions of the litellm Python package were published to PyPI:

  • v1.82.7 — malicious code injected into proxy_server.py (base64-encoded)
  • v1.82.8 — added a litellm_init.pth file that executes on every Python interpreter startup

Available for ~3 hours before PyPI quarantined them. LiteLLM has ~95 million monthly downloads. The attacker compromised BerriAI's PyPI token by poisoning the aquasecurity/trivy-action GitHub Action.

Three-stage payload: credential harvesting, AES-256+RSA-4096 encrypted exfiltration to C2, persistent backdoor polling every 50 minutes. If K8s credentials found, deploys privileged node-setup-* pods for lateral movement.

Axios npm Compromise (March 31, 2026)

The axios npm package (100M weekly downloads) was compromised via maintainer account takeover attributed to North Korea's UNC1069/BlueNoroff:

  • v1.14.1 (tagged latest) and v0.30.4 (tagged legacy)
  • Injected phantom dependency plain-crypto-js@4.2.1 with postinstall RAT dropper
  • Cross-platform RAT payloads: PowerShell (Windows), compiled binary (macOS), Python script (Linux)
  • Self-deleting dropper with double-layer obfuscation

Available for ~3 hours. C2 at sfrclak.com:8000.

What This Scanner Detects

The scanner runs a 5-phase pipeline for each threat profile:

Phase What It Looks For
1 Package metadata directories across the filesystem (PyPI: dist-info/egg-info; npm: node_modules/*/package.json)
2 Package version from metadata — flags compromised versions
3 IOC artifacts: backdoor files, persistence mechanisms, temp staging files, C2 network connections, suspicious Kubernetes pods, phantom dependencies, Windows Registry/Tasks
4 Source files and dependency configs referencing the package, flagging pinned compromised versions
5 Per-threat summary, verdicts, and remediation guidance

Limitations

  • Cannot detect exfiltrated secrets. Credential rotation is required regardless of scan results.
  • Artifacts may have been cleaned up. Absence of IOC files does not prove the system was never compromised.
  • Does not inspect Docker image layers, CI/CD runner caches, or remote systems.
  • Root-owned paths (/root on Linux) are excluded.
  • Windows Registry scanning is best-effort.

Platform Support

Feature Linux macOS Windows 10/11
Package detection /home, /opt, /usr, /srv, /var /Users, /opt/homebrew, /usr/local, /Library %USERPROFILE%, %APPDATA%, Program Files
Conda/pipx/nvm detection /opt/conda, ~/.local/share/pipx Homebrew Caskroom, ~/.local/share/pipx %LOCALAPPDATA%\Miniconda3, %LOCALAPPDATA%\pipx
Network connections ss -tnp lsof -i -P -n netstat -ano
ANSI terminal colors Native Native Auto-enabled via Virtual Terminal Processing

If Compromise Is Detected

Assume ALL secrets on the affected machine are compromised. The scanner provides threat-specific remediation steps. General guidance:

  1. Rotate credentials immediately — SSH keys, cloud credentials, API keys, database passwords, CI/CD tokens
  2. Remove malicious artifacts — see scanner output for specific paths
  3. Fix the package — install the safe version indicated by the scanner
  4. Update pinned versions — check all dependency files for compromised version pins
  5. Block C2 domains — at DNS/firewall level
  6. Audit cloud provider logs — check for unauthorized API calls

Advisories and References

LiteLLM

ID Source
PYSEC-2026-2 Python Packaging Authority (PyPA)
SNYK-PYTHON-LITELLM-15762713 Snyk
GitHub Issue #24512 Initial disclosure

Research: Endor Labs, Datadog Security Labs, Snyk, Sonatype, StepSecurity

Axios

ID Source
GHSA-fw8c-xr5c-95f9 GitHub Advisory
MAL-2026-2306 Malicious Package Identifier

Research: Snyk, Socket, Huntress, Datadog Security Labs, Wiz

Known IOC Hashes (SHA-256)

File SHA-256
litellm_init.pth (v1.82.8) 71e35aef03099cd1f2d6446734273025a163597de93912df321ef118bf135238
proxy_server.py (v1.82.7) a0d229be8efcb2f9135e2ad55ba275b76ddcfeb55fa4370e0a522a5bdee0120b
sysmon.py (dropped backdoor) 6cf223aea68b0e8031ff68251e30b6017a0513fe152e235c26f248ba1e15c92a

Project Structure

scan_litellm_compromise/
  threats/               Threat profile TOML files (user-extensible)
    litellm-2026-03.toml   LiteLLM PyPI compromise
    axios-2026-03.toml     Axios npm compromise
  threat_profile.py      ThreatProfile dataclass + TOML loader
  ecosystem_base.py      EcosystemPlugin protocol + factory
  ecosystem_pypi.py      PyPI: dist-info, METADATA, Python patterns
  ecosystem_npm.py       npm: node_modules, package.json, JS/TS patterns
  scanner.py             Orchestrator (multi-threat CLI)
  config.py              Generic constants (skip dirs)
  models.py              Typed data structures
  formatting.py          Terminal output (ANSI with Windows support)
  platform_policy.py     Platform abstraction (Strategy pattern)
  platform_linux.py      Linux paths and commands
  platform_darwin.py     macOS paths and commands
  platform_windows.py    Windows paths and commands
  ioc_windows.py         Windows-only IOC checks (Registry, Tasks)
  discovery.py           Phase 1 — find package metadata
  version_checker.py     Phase 2 — read package version
  ioc_scanner.py         Phase 3 — IOC artifact detection
  source_scanner.py      Phase 4 — source/config file scanning
  report.py              Phase 5 — summary and remediation
tests/                   pytest test suite (230 tests)
run_scan.py              Direct entry point
run_scan.bat             Double-click launcher for Windows

Disclaimer

This tool is provided as-is, with no warranty of any kind. It attempts to find known indicators of supply chain compromises but cannot guarantee complete detection. A clean scan does not mean your system was unaffected. Always perform credential rotation if there is any possibility that a compromised package was installed in your environment, even briefly.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

scan_litellm_compromise-0.4.3.tar.gz (41.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

scan_litellm_compromise-0.4.3-py3-none-any.whl (37.5 kB view details)

Uploaded Python 3

File details

Details for the file scan_litellm_compromise-0.4.3.tar.gz.

File metadata

  • Download URL: scan_litellm_compromise-0.4.3.tar.gz
  • Upload date:
  • Size: 41.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for scan_litellm_compromise-0.4.3.tar.gz
Algorithm Hash digest
SHA256 dab5b9aea2e0fe858a0184c26c4d671bdb580980c31453248e658ab63abca9f5
MD5 16f1175fccde8d02928a1cfe54f44ff7
BLAKE2b-256 ae2d2bcd97a46b6e69b1cc29f65fa2c7e5a4fc460588c470f2ac9e7a65e5d381

See more details on using hashes here.

Provenance

The following attestation bundles were made for scan_litellm_compromise-0.4.3.tar.gz:

Publisher: pypi_publish.yml on CognitiveSand/scan_litellm_compromise

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file scan_litellm_compromise-0.4.3-py3-none-any.whl.

File metadata

File hashes

Hashes for scan_litellm_compromise-0.4.3-py3-none-any.whl
Algorithm Hash digest
SHA256 f7980c52ca089a08502976fa55a34673fde98934ab76bbd95bb827d54369da1b
MD5 9e458f5934c2899e398a001be5a232d0
BLAKE2b-256 14c29ed76a258306834cd7b3a089e7f5dc7d4ef700ffd80c58ea2e652ff2f0a0

See more details on using hashes here.

Provenance

The following attestation bundles were made for scan_litellm_compromise-0.4.3-py3-none-any.whl:

Publisher: pypi_publish.yml on CognitiveSand/scan_litellm_compromise

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page