diff --git a/changelog.d/fixes/6944-chatgpt-web-citation-backslash-escape.md b/changelog.d/fixes/6944-chatgpt-web-citation-backslash-escape.md new file mode 100644 index 0000000000..cefb3d8800 --- /dev/null +++ b/changelog.d/fixes/6944-chatgpt-web-citation-backslash-escape.md @@ -0,0 +1 @@ +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl diff --git a/open-sse/executors/chatgpt-web/citations.ts b/open-sse/executors/chatgpt-web/citations.ts index 395a18317c..2f61830ad8 100644 --- a/open-sse/executors/chatgpt-web/citations.ts +++ b/open-sse/executors/chatgpt-web/citations.ts @@ -49,7 +49,15 @@ function asArray(value: unknown): unknown[] { } function markdownLinkText(value: string): string { - return value.replace(/\[/g, "\\[").replace(/\]/g, "\\]").replace(/\n/g, " ").trim(); + // Escape the backslash first — otherwise a label ending in (or containing) a + // backslash leaks past the `[…]` escaping and breaks the generated link, e.g. + // `[Path C:\](url)` where the trailing `\` escapes the closing bracket. + return value + .replace(/\\/g, "\\\\") + .replace(/\[/g, "\\[") + .replace(/\]/g, "\\]") + .replace(/\n/g, " ") + .trim(); } function markdownUrl(value: string): string { diff --git a/tests/unit/chatgpt-web-citations-escape.test.ts b/tests/unit/chatgpt-web-citations-escape.test.ts new file mode 100644 index 0000000000..540183e959 --- /dev/null +++ b/tests/unit/chatgpt-web-citations-escape.test.ts @@ -0,0 +1,50 @@ +// ChatGPT-web citation link-text escaping (CodeQL js/incomplete-sanitization, +// PR #6569 release-blocker). +// +// `markdownLinkText()` builds the `[text]` half of a Markdown link from an +// untrusted citation label. It escaped `[` and `]` but NOT the backslash +// itself, so a label ending in (or containing) a backslash produced a broken +// link: e.g. `[Path C:\](url)` — the trailing `\` escapes the closing `]`, +// consuming the link's bracket. The escape character must be escaped first. + +import test from "node:test"; +import assert from "node:assert/strict"; + +const { cleanChatGptText } = await import( + "../../open-sse/executors/chatgpt-web/citations.ts" +); + +const S = ""; // marker start +const SEP = ""; // marker separator +const E = ""; // marker end + +// Build a raw `url` citation marker:  url 