fix: harden MCP endpoint after code review
Critical: the MCP SDK auto-enables DNS-rebinding protection when its host parameter is left at the 127.0.0.1 default, hard-coding a loopback-only Host allow-list. Every remote client (the only deployment this feature targets) was refused with HTTP 421 before auth or the tool ran. Now driven by a new MCP_ALLOWED_HOSTS setting, with '*' as an explicit, logged opt-out. Also bounds query/top_k to match AskRequest (top_k is amplified 4x downstream, so an unbounded value was a resource-exhaustion vector), decodes the Authorization header as latin-1 per the ASGI spec instead of raising a 500 on malformed bytes, and returns WWW-Authenticate on 401 per RFC 7235. Moves the psycopg2 import guard into backend/tests/conftest.py: duplicated across four test modules, it only worked because of alphabetical collection order, and any earlier-sorting package would have reintroduced a live connection attempt against the production database. Registers the mcp module in the authoritative backend architecture doc. 84 backend tests pass. Verified against a live server: allowed remote Host returns a valid initialize result, unknown Host returns 421, missing token returns 401 with WWW-Authenticate. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
"""Shared pytest fixtures and import-time guards for the backend test suite.
|
||||
|
||||
pytest imports this file before any test module beneath backend/tests/, which
|
||||
makes it the only reliable place to install import-time guards: individual test
|
||||
modules cannot guarantee they run first, because collection order follows
|
||||
directory names.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
# app/shared/bootstrap.py (the composition root) eagerly imports the Postgres
|
||||
# store modules, which do `import psycopg2` at their own module scope and later
|
||||
# open a real connection pool. Any test that transitively imports bootstrap
|
||||
# would therefore bind the real driver and attempt a live TCP connection to the
|
||||
# configured production database, surfacing as a multi-second timeout rather
|
||||
# than an obvious error. Binding mocks here — before the first test module is
|
||||
# imported — makes that impossible regardless of collection order.
|
||||
# setdefault (not assignment) keeps a real psycopg2 in place if something has
|
||||
# already imported it deliberately.
|
||||
_mock_psycopg2 = MagicMock()
|
||||
_mock_psycopg2.extras = MagicMock()
|
||||
sys.modules.setdefault("psycopg2", _mock_psycopg2)
|
||||
sys.modules.setdefault("psycopg2.extras", _mock_psycopg2.extras)
|
||||
sys.modules.setdefault("psycopg2.pool", MagicMock())
|
||||
Reference in New Issue
Block a user