fix(copilot/sdk-proxy): address CodeQL findings + isort drift

CodeQL flagged two issues in the new compat proxy:

1. `py/clear-text-logging-sensitive-data` (high) — logging
   `self._target_base_url` could leak credentials if a future caller
   passed a URL containing them. Switched to logging only the host
   component (and the local 127.0.0.1 port) so even an
   accidentally-credentialled base URL stays out of logs.

2. `py/stack-trace-exposure` (medium) — returning the upstream
   exception text in the 502 response body could leak internal
   hostnames or stack frames to the client. Changed to a generic
   "upstream error" string; the detailed exception is still logged
   server-side.

Also fixes an isort sorting drift in the test file (private
underscore-prefixed names must sort before public names — local
isort accepted the order, CI's isort did not).
This commit is contained in:
majdyz
2026-04-11 07:55:53 +00:00
parent 0f00972efc
commit 93f27ffdf6
2 changed files with 16 additions and 6 deletions

View File

@@ -62,6 +62,7 @@ import asyncio
import json
import logging
from typing import Any
from urllib.parse import urlparse
import aiohttp
from aiohttp import web
@@ -295,10 +296,16 @@ class OpenRouterCompatProxy:
raise RuntimeError("Compat proxy server has no listening sockets.")
self._port = sockets[0].getsockname()[1]
self._runner = runner
# Log only the host of the upstream — never the full URL — so a
# base URL that happens to embed credentials (e.g. via a path
# token, though OpenRouter doesn't do this) cannot leak into
# logs. CodeQL `py/clear-text-logging-sensitive-data` defends
# against this case.
upstream_host = urlparse(self._target_base_url).netloc or "<unknown>"
logger.info(
"OpenRouter compat proxy listening on %s -> %s",
self.local_url,
self._target_base_url,
"OpenRouter compat proxy listening on 127.0.0.1:%d -> %s",
self._port,
upstream_host,
)
async def stop(self) -> None:
@@ -359,10 +366,14 @@ class OpenRouterCompatProxy:
allow_redirects=False,
)
except aiohttp.ClientError as e:
# Log the detailed error for ops, but return a generic
# message to the caller — exception strings can leak
# internal hostnames, ports, or stack frames (CodeQL
# `py/stack-trace-exposure`).
logger.warning(
"OpenRouter compat proxy upstream error: %s (url=%s)", e, upstream_url
)
return web.Response(status=502, text=f"upstream error: {e}")
return web.Response(status=502, text="upstream error")
# Stream the response back unchanged (apart from hop-by-hop
# header filtering).

View File

@@ -23,9 +23,9 @@ import pytest
from aiohttp import web
from backend.copilot.sdk.openrouter_compat_proxy import (
OpenRouterCompatProxy,
_FORBIDDEN_BETA_TOKENS,
_HOP_BY_HOP_HEADERS,
OpenRouterCompatProxy,
clean_request_body_bytes,
clean_request_headers,
strip_forbidden_anthropic_beta_header,
@@ -33,7 +33,6 @@ from backend.copilot.sdk.openrouter_compat_proxy import (
strip_tool_reference_blocks,
)
# ---------------------------------------------------------------------------
# strip_tool_reference_blocks
# ---------------------------------------------------------------------------