mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-11 08:38:24 +00:00
fix: prevent sentinel from leaking into /v1/models API response (#23850)
The fail-closed sentinel "__access_group_no_models__" was passing through get_complete_model_list() unchanged and reaching callers that return model lists directly to end-users, causing it to appear as a model ID in GET /v1/models responses. - Extract sentinel to named constant ACCESS_GROUP_NO_MODELS_SENTINEL in model_checks.py so all references stay in sync - Strip the sentinel from all_models before returning in utils.py - Strip it from all_models_str in proxy_server.py as a safety net Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2d793a3acd
commit
82d01db3f4
3 changed files with 16 additions and 1 deletions
|
|
@ -132,6 +132,13 @@ def get_key_models(
|
|||
return all_models
|
||||
|
||||
|
||||
# Sentinel used by get_key_models_with_db_access_groups to signal "key has
|
||||
# access_group_ids but none resolved to any model" so that get_complete_model_list()
|
||||
# does not fall through to team_models (fail-closed). Callers that return model
|
||||
# lists to end-users MUST strip this value before responding.
|
||||
ACCESS_GROUP_NO_MODELS_SENTINEL = "__access_group_no_models__"
|
||||
|
||||
|
||||
async def get_key_models_with_db_access_groups(
|
||||
user_api_key_dict: UserAPIKeyAuth,
|
||||
proxy_model_list: List[str],
|
||||
|
|
@ -168,7 +175,7 @@ async def get_key_models_with_db_access_groups(
|
|||
# Fail-closed: if the access group is configured but resolves to nothing
|
||||
# (deleted group, DB unavailable, or empty group), use a sentinel so
|
||||
# get_complete_model_list() does NOT fall through to team_models.
|
||||
key_models = db_models if db_models else ["__access_group_no_models__"]
|
||||
key_models = db_models if db_models else [ACCESS_GROUP_NO_MODELS_SENTINEL]
|
||||
|
||||
return key_models
|
||||
|
||||
|
|
|
|||
|
|
@ -275,6 +275,7 @@ from litellm.proxy.auth.auth_utils import check_response_size_is_safe
|
|||
from litellm.proxy.auth.handle_jwt import JWTHandler
|
||||
from litellm.proxy.auth.litellm_license import LicenseCheck
|
||||
from litellm.proxy.auth.model_checks import (
|
||||
ACCESS_GROUP_NO_MODELS_SENTINEL,
|
||||
get_all_fallbacks,
|
||||
get_complete_model_list,
|
||||
get_key_models,
|
||||
|
|
@ -10871,6 +10872,8 @@ async def model_info_v1( # noqa: PLR0915
|
|||
infer_model_from_keys=general_settings.get("infer_model_from_keys", False),
|
||||
llm_router=llm_router,
|
||||
)
|
||||
# Strip the fail-closed sentinel — it must never appear in the /v1/models response.
|
||||
all_models_str = [m for m in all_models_str if m != ACCESS_GROUP_NO_MODELS_SENTINEL]
|
||||
|
||||
if len(all_models_str) > 0:
|
||||
_relevant_models = []
|
||||
|
|
|
|||
|
|
@ -5516,6 +5516,7 @@ async def get_available_models_for_user(
|
|||
"""
|
||||
from litellm.proxy.auth.auth_checks import get_team_object
|
||||
from litellm.proxy.auth.model_checks import (
|
||||
ACCESS_GROUP_NO_MODELS_SENTINEL,
|
||||
get_complete_model_list,
|
||||
get_key_models_with_db_access_groups,
|
||||
get_team_models,
|
||||
|
|
@ -5581,6 +5582,10 @@ async def get_available_models_for_user(
|
|||
only_model_access_groups=only_model_access_groups,
|
||||
)
|
||||
|
||||
# Strip the fail-closed sentinel before returning to callers — it must never
|
||||
# appear in a model listing response (e.g. GET /v1/models).
|
||||
all_models = [m for m in all_models if m != ACCESS_GROUP_NO_MODELS_SENTINEL]
|
||||
|
||||
return all_models
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue