LiteLLM v1.59.8 Supply Chain Attack: Routerly Is Not Affected

Carlo Satta 4 min read

A community member (VolkanSah) opened an issue on the Routerly repository reporting a supply chain attack on the litellm PyPI package, specifically version 1.59.8. The compromised package was reported to contain a backdoor designed to exfiltrate LLM API keys through environment variables, representing a critical risk for any routing or proxy layer that handles provider credentials.

This post explains why Routerly is not affected, and what we fixed anyway.

The incident

The litellm package is a widely used Python library for calling LLM APIs with a unified interface. Version 1.59.8 on PyPI was reportedly found to contain malicious code that reads API keys from environment variables and sends them to an external server. Any Python application or DevAI toolchain that pulled this version would have silently exposed its provider credentials.

Reported details are available in GitHub issue #22 and the source referenced there.

Why Routerly is not affected

Routerly is a pure TypeScript / Node.js application. It has no dependency on litellm, no Python runtime requirement, and no PyPI package in its dependency tree. The compromised package cannot reach the Routerly codebase or any deployment of it.

This can be verified directly:

  • The package manifest (package.json) lists only npm packages.
  • There is no requirements.txt, no pyproject.toml, and no Python file anywhere in the repository.
  • The Dockerfile uses the official node:20-alpine base image with no Python layer.

What the report triggered: a full security audit

Although Routerly was not affected by this specific incident, the report was an opportunity to run a complete audit. We found and fixed three unrelated vulnerabilities, all of OWASP classification:

1. SSRF via webhook URL (CWE-918)

An admin user could configure a webhook notification URL. There was no validation of the destination. A malicious or misconfigured URL could have triggered requests to internal network addresses, cloud metadata endpoints (such as 169.254.169.254), or loopback interfaces, allowing an attacker with admin access to probe the internal network.

Fix: Added a validateWebhookUrl() function that blocks RFC-1918 private ranges, loopback addresses, link-local ranges, and cloud metadata endpoints before any outbound fetch.

2. Broken access control on GET /api/settings (CWE-284)

Any authenticated user, regardless of role, could call GET /api/settings and read the full settings object, which included SMTP credentials, AWS keys, and other notification configuration secrets.

Fix: The endpoint now requires the user:write permission. Read-only users and project-scoped tokens can no longer access this endpoint.

3. Weak password hashing (CWE-916)

Dashboard user passwords were hashed with SHA-256 without a salt. This is vulnerable to rainbow table attacks: a pre-computed table of common passwords and their SHA-256 hashes can crack these instantly.

Fix: Replaced with bcrypt at cost factor 12. Existing SHA-256 hashes are transparently migrated to bcrypt on the user’s next successful login, with no forced password reset required.

Supply chain hardening

Beyond the three code vulnerabilities, we also tightened the supply chain:

  • Dockerfile: replaced npm install with npm ci and ensured package-lock.json is copied before the install step, so the lockfile is enforced rather than ignored
  • CI pipeline: added npm audit --audit-level=high as a required step; the build fails on any high or critical npm vulnerability
  • Dependabot: configured for weekly automated updates to both npm packages and the base Docker image

All changes shipped in PR #23. Test suite: 41/41 passing, 0 npm audit vulnerabilities, 0 TypeScript errors.

Recommendations for users

If you are running Routerly:

  • No action is required in response to the litellm incident specifically.
  • If you are on any release older than the current one, we recommend updating to pick up the three vulnerability fixes above.
  • If you run Routerly in a multi-user environment where not all dashboard users are fully trusted, the CWE-284 fix is particularly relevant.

To update via Docker:

docker pull inebrio/routerly:latest
docker stop routerly && docker rm routerly
docker run -d \
  --name routerly \
  -p 3000:3000 \
  -v routerly_data:/data \
  -e ROUTERLY_HOME=/data \
  --restart unless-stopped \
  inebrio/routerly:latest

To update via the installer:

curl -fsSL https://www.routerly.ai/install.sh | bash

The installer detects an existing installation and presents an update option.

Reporting vulnerabilities

The SECURITY.md file in the repository describes the vulnerability reporting process, coordinated disclosure policy, and current supply chain practices. We follow a 90-day disclosure timeline for reported issues.


Sources