From ac83ce12c3466dc96a97ecc8c76e00352d4308c5 Mon Sep 17 00:00:00 2001 From: DeFine <76160388+its-DeFine@users.noreply.github.com> Date: Sun, 8 Feb 2026 16:00:14 +0200 Subject: [PATCH] security: redact query strings and WS payloads from logs --- src/index.ts | 24 ++++++++++++++---------- src/routes/cdp.ts | 3 ++- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/index.ts b/src/index.ts index 3ee1f5c20..281b00fd0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -114,7 +114,8 @@ const app = new Hono(); // Middleware: Log every request app.use('*', async (c, next) => { const url = new URL(c.req.url); - console.log(`[REQ] ${c.req.method} ${url.pathname}${url.search}`); + // Never log query strings: they frequently contain `?token=...` or other secrets. + console.log(`[REQ] ${c.req.method} ${url.pathname}${url.search ? ' ?[redacted]' : ''}`); console.log(`[REQ] Has ANTHROPIC_API_KEY: ${!!c.env.ANTHROPIC_API_KEY}`); console.log(`[REQ] DEV_MODE: ${c.env.DEV_MODE}`); console.log(`[REQ] DEBUG_ROUTES: ${c.env.DEBUG_ROUTES}`); @@ -265,8 +266,8 @@ app.all('*', async (c) => { // Proxy to Moltbot with WebSocket message interception if (isWebSocketRequest) { console.log('[WS] Proxying WebSocket connection to Moltbot'); - console.log('[WS] URL:', request.url); - console.log('[WS] Search params:', url.search); + // Avoid logging full URLs and query strings (often contain tokens/secrets). + console.log('[WS] Path:', url.pathname); // Get WebSocket connection to the container const containerResponse = await sandbox.wsConnect(request, MOLTBOT_PORT); @@ -294,7 +295,10 @@ app.all('*', async (c) => { // Relay messages from client to container serverWs.addEventListener('message', (event) => { - console.log('[WS] Client -> Container:', typeof event.data, typeof event.data === 'string' ? event.data.slice(0, 200) : '(binary)'); + // Never log WS payloads; they can contain auth tokens and user content. + const kind = typeof event.data === 'string' ? 'text' : 'binary'; + const size = typeof event.data === 'string' ? event.data.length : (event.data as ArrayBuffer).byteLength; + console.log('[WS] Client -> Container:', kind, `${size} bytes`); if (containerWs.readyState === WebSocket.OPEN) { containerWs.send(event.data); } else { @@ -304,22 +308,21 @@ app.all('*', async (c) => { // Relay messages from container to client, with error transformation containerWs.addEventListener('message', (event) => { - console.log('[WS] Container -> Client (raw):', typeof event.data, typeof event.data === 'string' ? event.data.slice(0, 500) : '(binary)'); + const kind = typeof event.data === 'string' ? 'text' : 'binary'; + const size = typeof event.data === 'string' ? event.data.length : (event.data as ArrayBuffer).byteLength; + console.log('[WS] Container -> Client:', kind, `${size} bytes`); let data = event.data; // Try to intercept and transform error messages if (typeof data === 'string') { try { const parsed = JSON.parse(data); - console.log('[WS] Parsed JSON, has error.message:', !!parsed.error?.message); if (parsed.error?.message) { - console.log('[WS] Original error.message:', parsed.error.message); parsed.error.message = transformErrorMessage(parsed.error.message, url.host); - console.log('[WS] Transformed error.message:', parsed.error.message); data = JSON.stringify(parsed); } } catch (e) { - console.log('[WS] Not JSON or parse error:', e); + // Not JSON; nothing to transform. } } @@ -365,7 +368,8 @@ app.all('*', async (c) => { }); } - console.log('[HTTP] Proxying:', url.pathname + url.search); + // Never log query strings: they frequently contain `?token=...` or other secrets. + console.log('[HTTP] Proxying:', url.pathname, url.search ? ' ?[redacted]' : ''); const httpResponse = await sandbox.containerFetch(request, MOLTBOT_PORT); console.log('[HTTP] Response status:', httpResponse.status); diff --git a/src/routes/cdp.ts b/src/routes/cdp.ts index 1d78e4911..6252735b2 100644 --- a/src/routes/cdp.ts +++ b/src/routes/cdp.ts @@ -391,7 +391,8 @@ async function initCDPSession(ws: WebSocket, env: MoltbotEnv): Promise { return; } - console.log('[CDP] Request:', request.method, request.params); + // Never log params: they can include sensitive data (headers, cookies, form values). + console.log('[CDP] Request:', request.method); try { const result = await handleCDPMethod(session, request.method, request.params || {}, ws);