criticalJun 26, 2026

CVE-2026-42208: semantic-router Unbounded litellm Pin Pulls Credential-Stealing Wheel

Shubham Kandhare
Security Engagement Manager, SecureLayer7

Installing semantic-router 0.1.8 through 0.1.14 could silently pull in a backdoored version of litellm that steals every credential on the machine the moment Python starts, with no import required.

Packagesemantic-router
Ecosystempip
Affected>= 0.1.8, < 0.1.15
Fixed in0.1.15

The problem

semantic-router declared `litellm>=1.61.3` with no upper bound. When `litellm==1.82.8` was the latest release on PyPI, a plain `pip install semantic-router` on any affected version resolved to that compromised wheel.

The malicious wheel shipped `litellm_init.pth` into `site-packages/`. Python's site module executes `.pth` file lines on every interpreter startup, so the payload fired automatically, no `import litellm` needed. It harvested SSH keys, cloud credentials, environment variables, Kubernetes configs, and `.env` files, then encrypted and exfiltrated everything to `https://models.litellm.cloud/` using AES-256-CBC plus an embedded RSA public key.

Proof of concept

bash
# Any pip install on affected semantic-router 0.1.8-0.1.14 during the exposure window
# could silently resolve litellm==1.82.8, dropping the malicious .pth file.
pip install "semantic-router>=0.1.8,<0.1.15"

# The installed .pth file contained the launcher line (from GHSA-5mg7-485q-xm76 / issue #24512):
# import os, subprocess, sys; subprocess.Popen([sys.executable, "-c", "import base64; exec(base64.b64decode('...'))"])
# This line fired on every Python startup. The double-base64 payload collected
# credentials and POSTed a tar.gz (X-Filename: tpcp.tar.gz) to https://models.litellm.cloud/

# Verify exposure:
pip show litellm  # if version is 1.82.7 or 1.82.8, treat system as compromised
find ~/.cache/uv -name 'litellm_init.pth'  # check uv cache too

The root cause in semantic-router is a missing upper bound on its litellm dependency. Pip's resolver picks the latest matching version, so `litellm>=1.61.3` resolved to `1.82.8` during the roughly 40-minute window it was live on PyPI on March 24, 2026.

The malicious wheel (published by the TeamPCP threat group using stolen PyPI credentials from a prior Trivy CI/CD compromise) used Python's `.pth` mechanism as the trigger. Because `.pth` files in `site-packages/` are processed by the `site` module at interpreter startup, the payload executed before any application code ran, on every Python invocation, not just when litellm was imported.

The payload was double-base64-encoded to evade naive grep, and the exfiltration domain `litellm.cloud` was chosen to resemble the legitimate `litellm.ai` domain.

The fix in semantic-router 0.1.15 raises the floor to `litellm>=1.83.7`, skipping both compromised versions. CWE-1395 (Dependency on Vulnerable Third-Party Component) and the supply chain nature of this issue map to CWE-506 (Embedded Malicious Code) as assigned.

The fix

Upgrade to `semantic-router>=0.1.15`, which pins `litellm>=1.83.7`. If you cannot upgrade immediately, add `litellm>=1.83.7` as an explicit constraint in your own project. Audit every environment where an affected install ran: check `pip show litellm`, search for `litellm_init.pth` in `site-packages/`, and look for persistence artifacts at `~/.config/sysmon/sysmon.py` and `~/.config/systemd/user/sysmon.service`.

Rotate all credentials (SSH keys, AWS/GCP/Azure tokens, API keys, database passwords, Kubernetes configs) that were accessible from any affected machine.

Reported by Callum McMahon (FutureSearch) - upstream discovery; litellm maintainers - triage.

References: [1][2]