From e4e93629190166ab8ab6c0fe362830e2bf550867 Mon Sep 17 00:00:00 2001 From: michelligabriele Date: Tue, 24 Mar 2026 14:50:48 +0100 Subject: [PATCH] default feature flag to False (opt-in), fix CodeQL log injection, update docs --- .../docs/proxy/credential_routing.md | 12 ++++++--- litellm/__init__.py | 2 +- litellm/proxy/litellm_pre_call_utils.py | 14 +++++++---- .../proxy/test_litellm_pre_call_utils.py | 25 +++++++++---------- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/docs/my-website/docs/proxy/credential_routing.md b/docs/my-website/docs/proxy/credential_routing.md index 9d0d702e591..2af57c6b496 100644 --- a/docs/my-website/docs/proxy/credential_routing.md +++ b/docs/my-website/docs/proxy/credential_routing.md @@ -236,9 +236,9 @@ The referenced credential can contain any combination of: Only keys present in the credential are applied. Keys already in the request (e.g. clientside `api_version`) are never overwritten. -## Disabling the Feature +## Enabling the Feature -The feature is enabled by default. To disable it globally: +This feature is **disabled by default** and must be explicitly enabled. To enable it: @@ -246,7 +246,7 @@ The feature is enabled by default. To disable it globally: ```yaml litellm_settings: - enable_model_config_credential_overrides: false + enable_model_config_credential_overrides: true ``` @@ -254,13 +254,17 @@ litellm_settings: ```bash -export LITELLM_ENABLE_MODEL_CONFIG_CREDENTIAL_OVERRIDES=false +export LITELLM_ENABLE_MODEL_CONFIG_CREDENTIAL_OVERRIDES=true ``` +:::info +The feature flag must be enabled before `model_config` entries in team/project metadata take effect. Without it, credential routing is completely inert — no metadata is read, no credentials are resolved. +::: + ## Related Documentation - [Adding LLM Credentials](./ui_credentials.md) — Create and manage reusable credentials diff --git a/litellm/__init__.py b/litellm/__init__.py index 4ed8895a57f..ba68b40fc44 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -318,7 +318,7 @@ return_response_headers: bool = ( False # get response headers from LLM Api providers - example x-remaining-requests, ) enable_json_schema_validation: bool = False -enable_model_config_credential_overrides: bool = True +enable_model_config_credential_overrides: bool = False enable_key_alias_format_validation: bool = ( False # opt-in validation of key_alias format on /key/generate and /key/update ) diff --git a/litellm/proxy/litellm_pre_call_utils.py b/litellm/proxy/litellm_pre_call_utils.py index b14c1fcccbd..472b3393e40 100644 --- a/litellm/proxy/litellm_pre_call_utils.py +++ b/litellm/proxy/litellm_pre_call_utils.py @@ -1363,7 +1363,7 @@ def _apply_credential_overrides_from_model_config( 5. Team default override (defaultconfig) 6. Deployment default (no action needed) """ - # Feature flag gate — operators can disable this with litellm.enable_model_config_credential_overrides = False + # Feature flag gate — disabled by default, opt in with litellm.enable_model_config_credential_overrides = True if not litellm.enable_model_config_credential_overrides: return @@ -1402,9 +1402,10 @@ def _apply_credential_overrides_from_model_config( credential_values = CredentialAccessor.get_credential_values(credential_name) if not credential_values: + _safe_cred = str(credential_name).replace("\n", "").replace("\r", "") verbose_proxy_logger.warning( "model_config references credential '%s' but it was not found or has no values", - credential_name, + _safe_cred, ) return @@ -1413,10 +1414,12 @@ def _apply_credential_overrides_from_model_config( if key in credential_values and key not in data: data[key] = credential_values[key] + _safe_model = str(model_name).replace("\n", "").replace("\r", "") + _safe_cred = str(credential_name).replace("\n", "").replace("\r", "") verbose_proxy_logger.debug( "Applied credential override '%s' for model '%s'", - credential_name, - model_name, + _safe_cred, + _safe_model, ) @@ -1461,10 +1464,11 @@ def _resolve_credential_from_model_config( ) if credential_name: return credential_name + _safe_name = str(name).replace("\n", "").replace("\r", "") verbose_proxy_logger.debug( "model_config entry '%s' found but has no litellm_credentials, " "falling through to defaultconfig", - name, + _safe_name, ) # Default check diff --git a/tests/test_litellm/proxy/test_litellm_pre_call_utils.py b/tests/test_litellm/proxy/test_litellm_pre_call_utils.py index 058c6b6e583..0973316dc4c 100644 --- a/tests/test_litellm/proxy/test_litellm_pre_call_utils.py +++ b/tests/test_litellm/proxy/test_litellm_pre_call_utils.py @@ -1830,8 +1830,10 @@ async def test_bearer_token_not_in_debug_logs(): @pytest.fixture() def setup_test_credentials(): - """Populate litellm.credential_list with test credentials, clean up after.""" + """Populate litellm.credential_list with test credentials and enable feature flag, clean up after.""" original = litellm.credential_list[:] + original_flag = litellm.enable_model_config_credential_overrides + litellm.enable_model_config_credential_overrides = True litellm.credential_list.extend( [ CredentialItem( @@ -1879,6 +1881,7 @@ def setup_test_credentials(): ) yield litellm.credential_list[:] = original + litellm.enable_model_config_credential_overrides = original_flag # --- Unit tests for _extract_credential_from_entry --- @@ -2304,8 +2307,9 @@ def test_apply_overrides_with_alias(setup_test_credentials): assert data["api_key"] == "key-hotel-eastus" -def test_apply_overrides_feature_flag_disabled(setup_test_credentials): - """Feature flag litellm.enable_model_config_credential_overrides disables the feature.""" +def test_apply_overrides_feature_flag_disabled_by_default(): + """Feature flag defaults to False — credential overrides are inert until explicitly enabled.""" + assert litellm.enable_model_config_credential_overrides is False data = {"model": "gpt-4"} user_api_key_dict = UserAPIKeyAuth( api_key="test-key", @@ -2315,16 +2319,11 @@ def test_apply_overrides_feature_flag_disabled(setup_test_credentials): } }, ) - original = litellm.enable_model_config_credential_overrides - try: - litellm.enable_model_config_credential_overrides = False - _apply_credential_overrides_from_model_config( - data=data, user_api_key_dict=user_api_key_dict - ) - assert "api_base" not in data - assert "api_key" not in data - finally: - litellm.enable_model_config_credential_overrides = original + _apply_credential_overrides_from_model_config( + data=data, user_api_key_dict=user_api_key_dict + ) + assert "api_base" not in data + assert "api_key" not in data def test_extract_credential_provider_hint_prefers_exact_match():