From 89aa13fdf3910eb1c3c97c78bc1b00f6cb7a3395 Mon Sep 17 00:00:00 2001 From: user <70670632+stuxf@users.noreply.github.com> Date: Wed, 29 Apr 2026 22:47:43 +0000 Subject: [PATCH] fix(static-assets): also wrap admin-only Vault token verification in async_safe_get MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Variant analysis on the unauthenticated /get_image SSRF surfaced one related sink in an admin-only endpoint: ``test_hashicorp_vault_connection`` in ``config_override_endpoints.py:402`` calls ``async_client.get(f"{vault_addr}/v1/auth/token/lookup-self")`` with no SSRF guard. ``vault_addr`` is admin-set, so the threat model is "admin misconfig (or attacker with admin creds) pivots Vault calls to cloud metadata or another internal IP." Same fix shape as the unauthenticated endpoints: wrap in ``async_safe_get`` so each redirect hop is re-validated and private networks are rejected. Admins running against a legitimate internal Vault should add the host to ``litellm.user_url_allowed_hosts`` — the existing escape hatch already used elsewhere in the codebase. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../management_endpoints/config_override_endpoints.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/litellm/proxy/management_endpoints/config_override_endpoints.py b/litellm/proxy/management_endpoints/config_override_endpoints.py index d78c5526e66..6e7cedd632f 100644 --- a/litellm/proxy/management_endpoints/config_override_endpoints.py +++ b/litellm/proxy/management_endpoints/config_override_endpoints.py @@ -391,7 +391,14 @@ async def test_hashicorp_vault_connection( detail=f"Vault authentication failed: {e}", ) - # Step 2: Verify the token is valid via token/lookup-self + # Step 2: Verify the token is valid via token/lookup-self. + # ``vault_addr`` is admin-set; wrapping in ``async_safe_get`` prevents + # a misconfigured (or attacker-influenced) value from pivoting the + # request to cloud metadata or another internal IP. Admins running + # against an internal Vault should add the host to + # ``litellm.user_url_allowed_hosts``. + from litellm.litellm_core_utils.url_utils import async_safe_get + try: async_client = get_async_httpx_client( llm_provider=httpxSpecialProvider.SecretManager @@ -399,7 +406,7 @@ async def test_hashicorp_vault_connection( lookup_url = f"{client.vault_addr}/v1/auth/token/lookup-self" if client.vault_namespace: headers["X-Vault-Namespace"] = client.vault_namespace - response = await async_client.get(lookup_url, headers=headers) + response = await async_safe_get(async_client, lookup_url, headers=headers) response.raise_for_status() except Exception as e: raise HTTPException(