fix(proxy): enforce model access checks on Bedrock passthrough routes

get_model_from_request could not resolve a model for /bedrock/... routes since it only checked the JSON body's model field and a small set of URL regexes, none matching Bedrock's passthrough path. This let common_checks skip the key/project model allowlist entirely for any Bedrock passthrough action (invoke, converse, and their streaming variants), while the same model was correctly blocked on /v1/chat/completions

Extract the model from the Bedrock endpoint path using the same helper the passthrough handler itself relies on, so the existing allowlist check applies uniformly across auth methods and call paths
This commit is contained in:
Riddhi04 2026-07-22 15:58:37 +04:00 committed by mateo-berri
parent 3244a034ac
commit 534ab1628d
2 changed files with 61 additions and 0 deletions

View file

@ -1981,6 +1981,17 @@ def get_model_from_request(
if vertex_match:
model = vertex_match.group(1)
if model is None and route.lower().startswith("/bedrock"):
from litellm.proxy.pass_through_endpoints.llm_passthrough_endpoints import (
_extract_model_from_bedrock_endpoint,
)
bedrock_endpoint = re.sub(r"^/bedrock/", "", route, flags=re.IGNORECASE)
try:
model = _extract_model_from_bedrock_endpoint(bedrock_endpoint)
except ValueError:
model = None
return model

View file

@ -428,6 +428,56 @@ def test_get_model_from_request_openai_deployment_route_still_works():
)
def test_get_model_from_request_bedrock_converse_passthrough():
assert (
get_model_from_request(
request_data={},
route="/bedrock/model/us.anthropic.claude-sonnet-4-6/converse",
)
== "us.anthropic.claude-sonnet-4-6"
)
def test_get_model_from_request_bedrock_invoke_passthrough():
assert (
get_model_from_request(
request_data={},
route="/bedrock/model/us.anthropic.claude-sonnet-4-6/invoke",
)
== "us.anthropic.claude-sonnet-4-6"
)
def test_get_model_from_request_bedrock_v2_converse_stream_passthrough():
assert (
get_model_from_request(
request_data={},
route="/bedrock/v2/model/us.anthropic.claude-sonnet-4-6/converse-stream",
)
== "us.anthropic.claude-sonnet-4-6"
)
def test_get_model_from_request_bedrock_model_id_with_slashes():
assert (
get_model_from_request(
request_data={},
route="/bedrock/model/aws/anthropic/model-name/invoke",
)
== "aws/anthropic/model-name"
)
def test_get_model_from_request_bedrock_unparseable_endpoint_returns_none():
assert (
get_model_from_request(
request_data={},
route="/bedrock/agents/some-agent-route",
)
is None
)
def test_get_model_from_request_includes_file_endpoint_header_model():
assert (
get_model_from_request(