## Summary

BerriAI LiteLLM proxy versions before the upstream parameterization fix contain an API-key authentication SQL injection in the database lookup for virtual keys. During authentication, an attacker-controlled `Authorization: Bearer ...` value reaches the combined verification-token lookup and, in vulnerable LiteLLM 1.83.6, is interpolated directly into a raw SQL string. The reproduction starts real LiteLLM proxy processes with PostgreSQL and proves that a remote request to `GET /model/info` using the injected bearer token `' OR EXISTS(SELECT 1 FROM pg_sleep(3)) --` causes PostgreSQL to execute the injected `pg_sleep(3)` expression and the endpoint to return authenticated model information. The same request against LiteLLM 1.83.7 is rejected immediately because the token is bound as a SQL parameter.

## Impact

- **Package/component affected:** BerriAI LiteLLM proxy authentication and database helper code, specifically the combined verification-token lookup in `litellm/proxy/utils.py` reached from `user_api_key_auth` on protected proxy/API endpoints.
- **Affected versions:** The reproduced vulnerable package is `litellm==1.83.6`. The fixed negative control is `litellm==1.83.7`. Upstream fix commit identified in the repository is `4dc416ee749122ca91e3bca095217478663419e7` (`fix(proxy): use parameterized query for combined_view token lookup`).
- **Risk level and consequences:** Critical. A remote unauthenticated attacker can place SQL syntax in the bearer token used by protected endpoints. In the reproduced path this bypasses virtual-key authentication and can execute database expressions. In a real deployment, the same primitive can be used for time/error/boolean SQL injection and can expose or manipulate LiteLLM gateway data such as virtual keys, configuration, and logs, depending on database privileges and SQL payload construction.

## Impact Parity

- **Disclosed/claimed maximum impact:** Unauthenticated SQL injection through proxy/admin API requests, leading to extraction or modification of LiteLLM database contents and compromise of gateway configuration, keys, and logs.
- **Reproduced impact from this run:** A production-path remote API request to the real LiteLLM proxy executed attacker-supplied SQL (`pg_sleep(3)`) through the `Authorization` bearer token. The vulnerable proxy returned HTTP 200 with model information, while an unknown-token baseline and the fixed build both returned HTTP 401. PostgreSQL logs captured both the interpolated vulnerable query and the fixed parameterized query.
- **Parity:** `full` for confirming the remote API SQL-injection vulnerability and fixed-version remediation; `partial` for the broader post-exploitation consequence because this run did not dump or modify sensitive gateway database records beyond demonstrating SQL execution and authentication bypass.
- **Not demonstrated:** Bulk extraction or modification of production secrets, provider credentials, or logs was intentionally not performed.

## Root Cause

The vulnerable code constructs a raw SQL query for the combined verification-token view by formatting the token value into the query text:

```python
WHERE v.token = '{token}'
```

The bearer token is attacker controlled. When Python optimization is enabled for product execution, the non-`sk-` assertion in the auth path is not enforced, allowing a token such as:

```text
' OR EXISTS(SELECT 1 FROM pg_sleep(3)) --
```

to reach the database helper. In `litellm==1.83.6`, this becomes SQL equivalent to:

```sql
WHERE v.token = '' OR EXISTS(SELECT 1 FROM pg_sleep(3)) --'
```

PostgreSQL evaluates the injected `EXISTS(SELECT 1 FROM pg_sleep(3))`, delaying the request and making the `WHERE` condition true for at least one seeded virtual-key row. That row is then treated as the authenticated key object for the protected endpoint.

The fix changes the helper to accept query arguments and uses a positional parameter:

```python
WHERE v.token = $1
response = await self._query_first_with_cached_plan_fallback(sql_query, hashed_token)
```

The upstream fix commit recorded in the reproduction evidence is:

- `4dc416ee749122ca91e3bca095217478663419e7` — `fix(proxy): use parameterized query for combined_view token lookup`

## Reproduction Steps

1. Use `bundle/repro/reproduction_steps.sh`.
2. The script:
   - Reuses or creates the deterministic project cache described by `bundle/project_cache_context.json`.
   - Installs/reuses `litellm==1.83.6` and `litellm==1.83.7` virtual environments.
   - Starts a local PostgreSQL instance and two real LiteLLM proxy processes, one vulnerable and one fixed.
   - Creates a virtual key through each running proxy via `/key/generate` so the verification-token table has a row.
   - Sends a baseline unknown-token request to `GET /model/info`.
   - Sends the injected bearer-token request to vulnerable `GET /model/info`.
   - Sends the identical injected bearer-token request to fixed `GET /model/info`.
   - Writes `bundle/repro/runtime_manifest.json` and `bundle/repro/result.txt` before exiting.
3. Expected evidence of reproduction:
   - Vulnerable request takes approximately three seconds and returns HTTP 200.
   - Fixed request returns HTTP 401 quickly.
   - PostgreSQL logs show the vulnerable raw query with `WHERE v.token = '' OR EXISTS(SELECT 1 FROM pg_sleep(3)) --'` and the fixed query with `WHERE v.token = $1` plus the payload only in bound parameters.

## Evidence

Primary artifacts:

- `bundle/repro/reproduction_steps.sh` — current-run reproducer.
- `bundle/repro/runtime_manifest.json` — runtime evidence manifest for the API endpoint proof.
- `bundle/repro/result.txt` — summarized timings/status codes.
- `bundle/logs/reproduction_steps.log` — full script output.
- `bundle/logs/source_delta.txt` — fix commit and patch hunk.
- `bundle/logs/postgres_repro.log` — PostgreSQL query evidence.
- `bundle/logs/vulnerable_injection.txt` — vulnerable endpoint response.
- `bundle/logs/fixed_injection.txt` — fixed endpoint response.
- `bundle/logs/proxy_vulnerable.log` and `bundle/logs/proxy_fixed.log` — LiteLLM proxy runtime logs.

Key current-run results from `bundle/repro/result.txt`:

```text
result=confirmed
baseline_time=0.013450
baseline_code=401
vuln_injection_time=3.012161
vuln_injection_code=200
fixed_injection_time=0.015421
fixed_injection_code=401
vulnerable_version=litellm 1.83.6
fixed_version=litellm 1.83.7
fixed_commit=4dc416ee749122ca91e3bca095217478663419e7
```

Vulnerable response evidence from `bundle/logs/vulnerable_injection.txt` shows a successful protected endpoint response:

```json
{"data":[{"model_name":"gpt-4o", ... }]}
```

Fixed response evidence from `bundle/logs/fixed_injection.txt` shows rejection of the exact same token:

```json
{"error":{"message":"Authentication Error, Invalid proxy server token passed... Unable to find token in cache or `LiteLLM_VerificationTokenTable`","type":"token_not_found_in_db","param":"key","code":"401"}}
```

PostgreSQL evidence from `bundle/logs/postgres_repro.log` includes the vulnerable query text:

```text
WHERE v.token = '' OR EXISTS(SELECT 1 FROM pg_sleep(3)) --'
```

The same log also includes the fixed query shape and parameter binding:

```text
WHERE v.token = $1
DETAIL:  Parameters: $1 = ''' OR EXISTS(SELECT 1 FROM pg_sleep(3)) --'
```

The runtime manifest records a real API endpoint path:

```json
{
  "entrypoint_kind": "endpoint",
  "entrypoint_detail": "GET /model/info with attacker-controlled Authorization Bearer token",
  "service_started": true,
  "healthcheck_passed": true,
  "target_path_reached": true,
  "runtime_stack": ["postgresql", "litellm-proxy"]
}
```

## Recommendations / Next Steps

- Upgrade LiteLLM proxy deployments to `1.83.7` or later, or to a downstream package containing commit `4dc416ee749122ca91e3bca095217478663419e7` or equivalent parameterization.
- Ensure all raw SQL helpers use parameterized arguments rather than f-string/interpolated query text.
- Add regression tests that send bearer tokens containing quotes, comments, and time-based SQL expressions through real protected proxy endpoints and verify they are rejected quickly.
- Rotate LiteLLM virtual keys, provider credentials, and any secrets stored in the LiteLLM database for deployments that exposed vulnerable versions to untrusted networks.
- Review PostgreSQL and proxy access logs for suspicious bearer-token values containing quotes, SQL comments, `UNION`, `SELECT`, `pg_sleep`, or similar SQL syntax.

## Additional Notes

- The reproduction script was executed successfully twice consecutively in the current run.
- The proof uses a real LiteLLM proxy process and a real PostgreSQL database; it does not mock the vulnerable SQL helper.
- The script bounds all HTTP requests with curl timeouts and writes all diagnostics under `bundle/logs/`.
- The proof avoids destructive SQL payloads. It uses `pg_sleep(3)` and endpoint response divergence to demonstrate SQL execution and authentication bypass without dumping sensitive database contents.
