fix(proxy): extend banned-params + admin-clear lists for NVIDIA Riva (VERIA-493) (#31742)

Two NVIDIA-Riva-specific fields consumed by the audio-transcription
handler via the provider's `optional_params` passthrough were not
covered by the proxy's existing banned-request-body list or the
admin-config clearing list applied on `api_base` BYOK override:

* `nvcf_function_id`
* `use_ssl`

Add both to `_BANNED_REQUEST_BODY_PARAMS` in
`litellm/proxy/auth/auth_utils.py` and to the kwargs-only list in
`_admin_config_fields_to_clear_on_base_override()` in
`litellm/router_utils/clientside_credential_handler.py`, next to the
analogous provider-specific entries already there (`aws_bedrock_*`,
OCI provider fields, etc.). Same admin opt-ins as every other entry
on those lists (`general_settings.allow_client_side_credentials`
proxy-wide, or `configurable_clientside_auth_params` per deployment).

Regression tests in `tests/test_litellm/proxy/auth/test_auth_utils.py`
cover root-level rejection, the historical `api_key` bypass, both
admin opt-in paths (proxy-wide and per-deployment), nested-container
smuggling via the existing recursive walk, and clearing on
`api_base` override. Mutation check verified.

Resolves VERIA-493
This commit is contained in:
yucheng-berri 2026-06-30 15:30:08 -07:00 committed by GitHub
parent a7d8c6f467
commit 41f9d8de7b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 186 additions and 0 deletions

View file

@ -278,6 +278,12 @@ _BANNED_REQUEST_BODY_PARAMS: Tuple[str, ...] = (
"s3_endpoint_url",
"sagemaker_base_url",
"deployment_url",
# NVIDIA Riva fields consumed by the audio-transcription handler
# via ``optional_params``. Banned for the same reason as the
# provider-specific entries above: a caller-supplied value retargets
# the request away from the admin's pinned configuration.
"nvcf_function_id",
"use_ssl",
# SDK-only field; also rejected outright in is_request_body_safe.
"model_list",
# Observability credentials, hosts, and project identifiers: derived

View file

@ -52,6 +52,13 @@ def _admin_config_fields_to_clear_on_base_override() -> List[str]:
"oci_tenancy",
"oci_key",
"oci_key_file",
# NVIDIA Riva fields — consumed by
# ``litellm/llms/nvidia_riva/audio_transcription/handler.py`` via
# optional_params and not declared on CredentialLiteLLMParams.
# Admin-pinned values must not flow through on a caller-redirected
# ``api_base`` for the same reason as the OCI entries above.
"nvcf_function_id",
"use_ssl",
]
return typed_fields + kwargs_only_fields

View file

@ -1520,6 +1520,42 @@ class TestGetDynamicLitellmParamsClearsAdminConfigOnBaseOverride:
assert "vertex_credentials" not in out
assert "vertex_project" not in out
def test_clears_nvcf_function_id_on_base_override(self):
from litellm.router_utils.clientside_credential_handler import (
get_dynamic_litellm_params,
)
admin_params = {
"model": "nvidia_riva/parakeet",
"api_base": "grpc.nvcf.nvidia.com:443",
"api_key": "nvapi-admin",
"nvcf_function_id": "admin-pinned-function",
}
out = get_dynamic_litellm_params(
litellm_params=dict(admin_params),
request_kwargs={"api_base": "self-hosted.example.com:50051"},
)
assert out["api_base"] == "self-hosted.example.com:50051"
assert "nvcf_function_id" not in out
def test_clears_use_ssl_on_base_override(self):
from litellm.router_utils.clientside_credential_handler import (
get_dynamic_litellm_params,
)
admin_params = {
"model": "nvidia_riva/parakeet",
"api_base": "grpc.nvcf.nvidia.com:443",
"api_key": "nvapi-admin",
"use_ssl": True,
}
out = get_dynamic_litellm_params(
litellm_params=dict(admin_params),
request_kwargs={"api_base": "self-hosted.example.com:50051"},
)
assert out["api_base"] == "self-hosted.example.com:50051"
assert "use_ssl" not in out
def test_caller_resupplied_value_overrides_admin_value_on_base_override(self):
# When the caller redirects ``api_base`` and *also* supplies their
# own value for one of the admin fields (e.g. ``organization``),
@ -1712,6 +1748,127 @@ class TestIsRequestBodySafeBlocksBedrockProjectOverride:
)
class TestIsRequestBodySafeBlocksNVCFFunctionOverride:
"""``nvcf_function_id`` is rejected as a request-body param unless the
admin opted in proxy-wide or per-deployment."""
def test_nvcf_function_id_in_request_body_is_rejected(self):
with pytest.raises(ValueError, match="nvcf_function_id"):
is_request_body_safe(
request_body={
"model": "nvidia_riva/parakeet",
"nvcf_function_id": "caller-supplied",
},
general_settings={},
llm_router=None,
model="nvidia_riva/parakeet",
)
def test_nvcf_function_id_with_api_key_still_rejected(self):
with pytest.raises(ValueError, match="nvcf_function_id"):
is_request_body_safe(
request_body={
"model": "nvidia_riva/parakeet",
"api_key": "sk-anything",
"nvcf_function_id": "caller-supplied",
},
general_settings={},
llm_router=None,
model="nvidia_riva/parakeet",
)
def test_admin_opt_in_proxy_wide_allows_nvcf_function_id(self):
assert (
is_request_body_safe(
request_body={
"model": "nvidia_riva/parakeet",
"nvcf_function_id": "byok-function-id",
},
general_settings={"allow_client_side_credentials": True},
llm_router=None,
model="nvidia_riva/parakeet",
)
is True
)
def test_admin_opt_in_per_deployment_allows_nvcf_function_id(self, monkeypatch):
"""The error message lists per-deployment ``configurable_clientside_auth_params``
as a second opt-in. Cover that path too so it can't silently regress."""
from litellm.proxy.auth import auth_utils
monkeypatch.setattr(
auth_utils,
"_allow_model_level_clientside_configurable_parameters",
lambda model, param, request_body_value, llm_router: param == "nvcf_function_id",
)
assert (
is_request_body_safe(
request_body={
"model": "nvidia_riva/parakeet",
"nvcf_function_id": "byok-function-id",
},
general_settings={},
llm_router=None,
model="nvidia_riva/parakeet",
)
is True
)
class TestIsRequestBodySafeBlocksRivaUseSsl:
"""``use_ssl`` is rejected as a request-body param unless the admin
opted in proxy-wide or per-deployment."""
def test_use_ssl_in_request_body_is_rejected(self):
with pytest.raises(ValueError, match="use_ssl"):
is_request_body_safe(
request_body={
"model": "nvidia_riva/parakeet",
"use_ssl": False,
},
general_settings={},
llm_router=None,
model="nvidia_riva/parakeet",
)
def test_admin_opt_in_proxy_wide_allows_use_ssl(self):
assert (
is_request_body_safe(
request_body={
"model": "nvidia_riva/parakeet",
"use_ssl": True,
},
general_settings={"allow_client_side_credentials": True},
llm_router=None,
model="nvidia_riva/parakeet",
)
is True
)
def test_admin_opt_in_per_deployment_allows_use_ssl(self, monkeypatch):
from litellm.proxy.auth import auth_utils
monkeypatch.setattr(
auth_utils,
"_allow_model_level_clientside_configurable_parameters",
lambda model, param, request_body_value, llm_router: param == "use_ssl",
)
assert (
is_request_body_safe(
request_body={
"model": "nvidia_riva/parakeet",
"use_ssl": True,
},
general_settings={},
llm_router=None,
model="nvidia_riva/parakeet",
)
is True
)
# ── is_request_body_safe nested-config recursion (VERIA-6) ────────────────────
@ -1748,6 +1905,22 @@ class TestIsRequestBodySafeNestedConfig:
model="milvus-store",
)
def test_nested_nvcf_function_id_in_metadata_blocked(self):
"""Smuggling ``nvcf_function_id`` via ``metadata`` / ``extra_body``
is the same shape as the VERIA-6 ``api_base`` bypass must be
rejected by the recursive walk so the NVCF override gate cannot
be sidestepped with nesting."""
with pytest.raises(ValueError, match="nvcf_function_id"):
is_request_body_safe(
request_body={
"model": "nvidia_riva/parakeet",
"litellm_metadata": {"nvcf_function_id": "attacker-via-metadata"},
},
general_settings={},
llm_router=None,
model="nvidia_riva/parakeet",
)
def test_nested_langfuse_host_in_embedding_config_blocked(self):
"""The recursion uses the *full* banned-param list, not a special
subset so any flag that's banned at the root is also banned