restrict wildcard matching to * patterns only

fnmatch treats ? and [...] as wildcards, so a model alias like
prod-[eu] would unintentionally match prod-e. Only apply fnmatch
when the pattern contains *, treating all other entries as exact
names. This matches the guard pattern used in guardrail_hooks.
This commit is contained in:
Jonathan Wrede 2026-05-10 20:31:10 +00:00
parent cb33674f72
commit bcc3472a52
2 changed files with 36 additions and 1 deletions

View file

@ -875,7 +875,9 @@ class JWTAuthManager:
return True
if model in role_based_models or any(
fnmatch.fnmatch(model, pattern) for pattern in role_based_models
fnmatch.fnmatch(model, pattern)
for pattern in role_based_models
if "*" in pattern
):
return True

View file

@ -2731,3 +2731,36 @@ class TestCanRbacRoleCallModelWildcard:
model="openai-gpt-4",
)
assert exc_info.value.status_code == 403
def test_fnmatch_metacharacters_treated_literally(self):
"""Model names with ? or [...] are exact aliases, not wildcard patterns."""
perms = [
RoleBasedPermissions(
role=LitellmUserRoles.INTERNAL_USER,
models=["prod-[eu]", "model-v2?"],
),
]
# Exact match works
assert JWTAuthManager.can_rbac_role_call_model(
rbac_role=LitellmUserRoles.INTERNAL_USER,
general_settings=self._settings(perms),
model="prod-[eu]",
)
assert JWTAuthManager.can_rbac_role_call_model(
rbac_role=LitellmUserRoles.INTERNAL_USER,
general_settings=self._settings(perms),
model="model-v2?",
)
# fnmatch would have matched these, but they should be rejected
with pytest.raises(HTTPException):
JWTAuthManager.can_rbac_role_call_model(
rbac_role=LitellmUserRoles.INTERNAL_USER,
general_settings=self._settings(perms),
model="prod-e",
)
with pytest.raises(HTTPException):
JWTAuthManager.can_rbac_role_call_model(
rbac_role=LitellmUserRoles.INTERNAL_USER,
general_settings=self._settings(perms),
model="model-v2x",
)