From ddac264463e2b5ff4947f2b9b143e8c43f8eb9d5 Mon Sep 17 00:00:00 2001 From: ashwin_kondapalli Date: Sat, 3 Oct 2026 22:45:12 -0500 Subject: [PATCH] Strip newlines at the workspace log sink Apply the canonical newline sanitizer inline at console.error so no user-influenced error text can forge log entries. --- src/workspace.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/workspace.ts b/src/workspace.ts index e1c7eec..9f1d6b2 100644 --- a/src/workspace.ts +++ b/src/workspace.ts @@ -30,7 +30,7 @@ export async function startWorkspace(options: WorkspaceOptions = {}): Promise<{ if (!["127.0.0.1", "localhost", "::1"].includes(host)) throw new Error("MCP-WEB-001 QA workspace binds only to loopback addresses"); const csrf = randomBytes(32).toString("base64url"); const runs = new Map(); const assets = resolve(dirname(fileURLToPath(import.meta.url)), "../workspace-assets"); - const server = createServer(async (req, res) => { securityHeaders(res); try { await route(req, res); } catch (error) { console.error("[MCP Rigor workspace] internal error:", messageOf(error)); json(res, 500, { error: { code: "MCP-WEB-500", message: "Internal server error" } }); } }); + const server = createServer(async (req, res) => { securityHeaders(res); try { await route(req, res); } catch (error) { console.error("[MCP Rigor workspace] internal error:", messageOf(error).replace(/\r?\n/g, " ")); json(res, 500, { error: { code: "MCP-WEB-500", message: "Internal server error" } }); } }); async function route(req: IncomingMessage, res: ServerResponse): Promise { const url = new URL(req.url ?? "/", `http://${req.headers.host}`); const method = req.method ?? "GET"; if (method !== "GET" && !authorized(req, csrf, `http://${req.headers.host}`)) return json(res, 403, { error: { code: "MCP-WEB-403", message: "Invalid workspace origin or CSRF token" } });