mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-11 22:51:28 +00:00
fix(mcp): fail closed on DB outage in BYOK credential check
`_check_byok_credential` previously returned silently when `prisma_client` was None, bypassing BYOK ownership validation during database-outage windows. Any proxy-authenticated user could invoke BYOK-protected MCP tools without a stored credential during the outage window. Now raises HTTP 503 with a structured error so the flow fails closed. Regression test asserts 503 is raised when `prisma_client` is None. Reported by @brodmart in GHSA-6762-2m23-5mxp. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f5b4564466
commit
fea402c580
2 changed files with 41 additions and 1 deletions
|
|
@ -1952,7 +1952,18 @@ if MCP_AVAILABLE:
|
|||
from litellm.proxy.proxy_server import prisma_client
|
||||
|
||||
if prisma_client is None:
|
||||
return
|
||||
# Fail closed on DB unavailability: returning here previously
|
||||
# bypassed the ownership check and let any proxy-authenticated
|
||||
# caller invoke BYOK tools during outage windows.
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail={
|
||||
"error": "byok_auth_unavailable",
|
||||
"server_id": mcp_server.server_id,
|
||||
"server_name": mcp_server.server_name or mcp_server.name,
|
||||
"message": "BYOK credential check requires a database connection.",
|
||||
},
|
||||
)
|
||||
|
||||
credential = await get_user_credential(
|
||||
prisma_client=prisma_client,
|
||||
|
|
|
|||
|
|
@ -564,6 +564,35 @@ async def test_check_byok_credential_has_credential():
|
|||
await _check_byok_credential(server, user_auth)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_check_byok_credential_db_unavailable_fails_closed():
|
||||
"""BYOK server with no prisma_client → 503, not silent pass.
|
||||
|
||||
Regression for GHSA-6762: previously returned silently, bypassing the
|
||||
ownership check during DB outage windows.
|
||||
"""
|
||||
from litellm.proxy._experimental.mcp_server.server import _check_byok_credential
|
||||
from litellm.proxy._types import UserAPIKeyAuth
|
||||
from litellm.types.mcp_server.mcp_server_manager import MCPServer
|
||||
|
||||
server = MCPServer(
|
||||
server_id="byok-4",
|
||||
name="byok-server",
|
||||
transport=MCPTransport.http,
|
||||
is_byok=True,
|
||||
)
|
||||
user_auth = UserAPIKeyAuth(user_id="user-55", api_key="sk-test")
|
||||
|
||||
with patch("litellm.proxy.proxy_server.prisma_client", None):
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
await _check_byok_credential(server, user_auth)
|
||||
|
||||
assert exc_info.value.status_code == 503
|
||||
detail: Any = exc_info.value.detail
|
||||
assert detail["error"] == "byok_auth_unavailable"
|
||||
assert detail["server_id"] == "byok-4"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Security regression tests for AO2kf_-9 / GHSA-jg3h:
|
||||
# Unauthenticated /v1/mcp/oauth/authorize previously allowed an attacker to
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue