From d4a01e48bcc5385cd1741a443d051a8769dbff7b Mon Sep 17 00:00:00 2001 From: ly-wang19 <94427531+ly-wang19@users.noreply.github.com> Date: Sat, 27 Jun 2026 05:43:11 +0800 Subject: [PATCH] fix(link-understanding): strip markdown links whose label contains brackets (#96476) Merged via squash. Prepared head SHA: 2d69ed259f4f55027f25be2332c15abf2e61aa2f Co-authored-by: ly-wang19 <94427531+ly-wang19@users.noreply.github.com> Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com> Reviewed-by: @vincentkoc --- src/link-understanding/detect.test.ts | 9 +++++++++ src/link-understanding/detect.ts | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/link-understanding/detect.test.ts b/src/link-understanding/detect.test.ts index 3b1737e507e0..20e540deee76 100644 --- a/src/link-understanding/detect.test.ts +++ b/src/link-understanding/detect.test.ts @@ -20,6 +20,15 @@ describe("extractLinksFromMessage", () => { expect(links).toEqual(["https://bare.example"]); }); + it("ignores markdown links whose label contains brackets", () => { + // The closing "]" inside the label must not break markdown stripping, otherwise + // the citation URL leaks out as a bare link (with a stray trailing ")"). + const links = extractLinksFromMessage( + "Check [my notes [v2]](https://internal.example/doc) for details", + ); + expect(links).toStrictEqual([]); + }); + it("blocks 127.0.0.1", () => { const links = extractLinksFromMessage("http://127.0.0.1/test https://ok.test"); expect(links).toEqual(["https://ok.test"]); diff --git a/src/link-understanding/detect.ts b/src/link-understanding/detect.ts index 480fd7c3992a..6118dd5aa646 100644 --- a/src/link-understanding/detect.ts +++ b/src/link-understanding/detect.ts @@ -3,7 +3,10 @@ import { isBlockedHostnameOrIp } from "../infra/net/ssrf.js"; import { DEFAULT_MAX_LINKS } from "./defaults.js"; // Remove markdown link syntax so only bare URLs are considered. -const MARKDOWN_LINK_RE = /\[[^\]]*]\((https?:\/\/\S+?)\)/gi; +// The link-text portion allows "]" that is not the closing "](" boundary so +// markdown links whose label contains brackets (e.g. "[my notes [v2]](...)") +// are still stripped instead of leaking their URL to BARE_LINK_RE. +const MARKDOWN_LINK_RE = /\[(?:[^\]]|](?!\())*]\((https?:\/\/\S+?)\)/gi; const BARE_LINK_RE = /https?:\/\/\S+/gi; function stripMarkdownLinks(message: string): string {