Merge pull request #26805 from BerriAI/litellm_auth_bypass_tag_based_routing

add test(tag-routing): prevent header regex bypass for strict plain t…
This commit is contained in:
yuneng-jiang 2026-05-01 00:08:57 -07:00 committed by GitHub
commit eab0075353
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 1 deletions

View file

@ -106,7 +106,8 @@ def _match_deployment(
# check either didn't run (no request tags) or failed (step 1 returned
# None). Block the regex path so it cannot circumvent the operator's
# strict-tag policy.
strict_tag_check_failed = not match_any and bool(deployment_tags)
deployment_has_plain_tags = deployment_tags is not None and len(deployment_tags) > 0
strict_tag_check_failed = not match_any and deployment_has_plain_tags
if deployment_tag_regex and header_strings and not strict_tag_check_failed:
regex_match = _is_valid_deployment_tag_regex(
deployment_tag_regex, header_strings

View file

@ -346,6 +346,34 @@ def test_tag_routing_with_list_of_tags_match_all():
assert not is_valid_deployment_tag(["default"], ["teamA"], match_any=False)
def test_strict_tag_routing_without_request_tags_blocks_header_regex_fallback():
"""
When tag_filtering_match_any=False, deployments with plain tags must require
those request tags before header regex can match. A spoofed User-Agent must
not route to a tagged deployment when the request has no tags.
"""
from litellm.router_strategy.tag_based_routing import _match_deployment
deployment = {
"model_name": "restricted-model",
"litellm_params": {
"model": "gpt-4o",
"tags": ["internal"],
"tag_regex": ["^User-Agent: internal-tool"],
},
}
assert (
_match_deployment(
deployment=deployment,
request_tags=None,
header_strings=["User-Agent: internal-tool"],
match_any=False,
)
is None
)
@pytest.mark.asyncio()
async def test_router_free_paid_tier_with_responses_api():
"""