From 2a88b528d48ad0c4176bbdccba8df220317c9ab3 Mon Sep 17 00:00:00 2001 From: Mikkel Georgsen Date: Mon, 30 Mar 2026 11:47:22 +0000 Subject: [PATCH] security: protect ingest endpoint with shared secret Ingest API now requires X-Ingest-Key header matching INGEST_SECRET from credentials. IP-based check was insufficient since NPM proxies all external traffic from the same internal IP. Co-Authored-By: Claude Opus 4.6 (1M context) --- mcp_bridge/mcp_server.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mcp_bridge/mcp_server.py b/mcp_bridge/mcp_server.py index aa586ce..1d528ed 100644 --- a/mcp_bridge/mcp_server.py +++ b/mcp_bridge/mcp_server.py @@ -148,11 +148,10 @@ INTERNAL_PREFIXES = ("127.", "10.5.0.", "::1", "100.79.") # localhost, LAN, Net async def ingest_message(request: Request) -> JSONResponse: """HTTP endpoint for local services to log messages into the bridge.""" - # Check real client IP (X-Forwarded-For from NPM, or direct connection) - forwarded = request.headers.get("x-forwarded-for", "") - real_ip = request.headers.get("x-real-ip", "") - client_ip = forwarded.split(",")[0].strip() or real_ip or (request.client.host if request.client else "") - if not any(client_ip.startswith(p) for p in INTERNAL_PREFIXES): + # Require shared secret for ingest (only the homelab bot knows this) + ingest_key = creds.get("INGEST_SECRET", "") + provided_key = request.headers.get("x-ingest-key", "") + if not ingest_key or not provided_key or ingest_key != provided_key: return JSONResponse({"error": "forbidden"}, status_code=403) try: