From 0a0c9c3264be3b8208b35e83fdd0eb5894421b78 Mon Sep 17 00:00:00 2001 From: kevensun <272731967@qq.com> Date: Fri, 13 Mar 2026 22:10:23 +0800 Subject: [PATCH] fix(mcp): escape error message in OAuth callback HTML to prevent XSS (CWE-79) Co-Authored-By: Claude Opus 4.6 --- packages/opencode/src/mcp/oauth-callback.ts | 6 ++- .../test/mcp/oauth-callback-xss.test.ts | 48 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 packages/opencode/test/mcp/oauth-callback-xss.test.ts diff --git a/packages/opencode/src/mcp/oauth-callback.ts b/packages/opencode/src/mcp/oauth-callback.ts index db8e621d6c..98d267c5ff 100644 --- a/packages/opencode/src/mcp/oauth-callback.ts +++ b/packages/opencode/src/mcp/oauth-callback.ts @@ -4,6 +4,10 @@ import { OAUTH_CALLBACK_PORT, OAUTH_CALLBACK_PATH } from "./oauth-provider" const log = Log.create({ service: "mcp.oauth-callback" }) +function escapeHtml(str: string): string { + return str.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'") +} + const HTML_SUCCESS = ` @@ -40,7 +44,7 @@ const HTML_ERROR = (error: string) => `

Authorization Failed

An error occurred during authorization.

-
${error}
+
${escapeHtml(error)}
` diff --git a/packages/opencode/test/mcp/oauth-callback-xss.test.ts b/packages/opencode/test/mcp/oauth-callback-xss.test.ts new file mode 100644 index 0000000000..89cd4c6742 --- /dev/null +++ b/packages/opencode/test/mcp/oauth-callback-xss.test.ts @@ -0,0 +1,48 @@ +import { describe, expect, test } from "bun:test" + +/** + * CWE-79: Cross-Site Scripting (XSS) + * File: packages/opencode/src/mcp/oauth-callback.ts + * + * HTML_ERROR interpolated error string directly into HTML template. + * Since error comes from URL query params (error, error_description), + * an attacker could craft a malicious OAuth callback URL to inject scripts. + */ + +function escapeHtml(str: string): string { + return str.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'") +} + +const HTML_ERROR = (error: string) => `
${escapeHtml(error)}
` + +describe("CWE-79: XSS in oauth-callback.ts HTML_ERROR", () => { + test("should escape script tags in error message", () => { + const result = HTML_ERROR('') + expect(result).not.toContain("