From 93f27ffdf614f579926b168dfc15712d7c67d555 Mon Sep 17 00:00:00 2001 From: majdyz Date: Sat, 11 Apr 2026 07:55:53 +0000 Subject: [PATCH] fix(copilot/sdk-proxy): address CodeQL findings + isort drift MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- .../copilot/sdk/openrouter_compat_proxy.py | 19 +++++++++++++++---- .../sdk/openrouter_compat_proxy_test.py | 3 +-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/autogpt_platform/backend/backend/copilot/sdk/openrouter_compat_proxy.py b/autogpt_platform/backend/backend/copilot/sdk/openrouter_compat_proxy.py index 600de018bd..9e617b4575 100644 --- a/autogpt_platform/backend/backend/copilot/sdk/openrouter_compat_proxy.py +++ b/autogpt_platform/backend/backend/copilot/sdk/openrouter_compat_proxy.py @@ -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 "" 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). diff --git a/autogpt_platform/backend/backend/copilot/sdk/openrouter_compat_proxy_test.py b/autogpt_platform/backend/backend/copilot/sdk/openrouter_compat_proxy_test.py index ca2a0725f6..46e8817485 100644 --- a/autogpt_platform/backend/backend/copilot/sdk/openrouter_compat_proxy_test.py +++ b/autogpt_platform/backend/backend/copilot/sdk/openrouter_compat_proxy_test.py @@ -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 # ---------------------------------------------------------------------------