[Security fix - CVE-2025-0330] - Leakage of Langfuse API keys in team exception handling (#9830)

* fix team id exception in get team config

* test_team_info_masking

* test ref
This commit is contained in:
Ishaan Jaff 2025-04-08 13:55:20 -07:00 committed by GitHub
parent 367f48004d
commit e6403b717c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 41 additions and 9 deletions

View file

@ -10,11 +10,12 @@ model_list:
api_key: fake-key
litellm_settings:
require_auth_for_metrics_endpoint: true
callbacks: ["prometheus"]
service_callback: ["prometheus_system"]
router_settings:
enable_tag_filtering: True # 👈 Key Change
default_team_settings:
- team_id: test_dev
success_callback: ["langfuse", "s3"]
langfuse_secret: secret-test-key
langfuse_public_key: public-test-key
- team_id: my_workflows
success_callback: ["langfuse", "s3"]
langfuse_secret: secret-workflows-key
langfuse_public_key: public-workflows-key

View file

@ -139,6 +139,7 @@ from litellm.litellm_core_utils.core_helpers import (
)
from litellm.litellm_core_utils.credential_accessor import CredentialAccessor
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
from litellm.litellm_core_utils.sensitive_data_masker import SensitiveDataMasker
from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler
from litellm.proxy._experimental.mcp_server.server import router as mcp_router
from litellm.proxy._experimental.mcp_server.tool_registry import (
@ -387,6 +388,7 @@ global_max_parallel_request_retries_env: Optional[str] = os.getenv(
"LITELLM_GLOBAL_MAX_PARALLEL_REQUEST_RETRIES"
)
proxy_state = ProxyState()
SENSITIVE_DATA_MASKER = SensitiveDataMasker()
if global_max_parallel_request_retries_env is None:
global_max_parallel_request_retries: int = 3
else:
@ -1397,7 +1399,9 @@ class ProxyConfig:
team_config: dict = {}
for team in all_teams_config:
if "team_id" not in team:
raise Exception(f"team_id missing from team: {team}")
raise Exception(
f"team_id missing from team: {SENSITIVE_DATA_MASKER.mask_dict(team)}"
)
if team_id == team["team_id"]:
team_config = team
break

View file

@ -162,3 +162,30 @@ async def test_aaaproxy_startup_master_key(mock_prisma, monkeypatch, tmp_path):
from litellm.proxy.proxy_server import master_key
assert master_key == test_resolved_key
def test_team_info_masking():
"""
Test that sensitive team information is properly masked
Ref: https://huntr.com/bounties/661b388a-44d8-4ad5-862b-4dc5b80be30a
"""
from litellm.proxy.proxy_server import ProxyConfig
proxy_config = ProxyConfig()
# Test team object with sensitive data
team1_info = {
"success_callback": "['langfuse', 's3']",
"langfuse_secret": "secret-test-key",
"langfuse_public_key": "public-test-key",
}
with pytest.raises(Exception) as exc_info:
proxy_config._get_team_config(
team_id="test_dev",
all_teams_config=[team1_info],
)
print("Got exception: {}".format(exc_info.value))
assert "secret-test-key" not in str(exc_info.value)
assert "public-test-key" not in str(exc_info.value)