From 2d58f16c93fd656f42671f4eaf004e32d5b5c784 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 24 Jul 2026 15:27:24 +0000 Subject: [PATCH] fix(webmention): remove polynomial-redos in Link header regex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CodeQL (js/polynomial-redos) flagged the `\s*` immediately before `(.*)$` in parseLinkHeader's regex: since `\s` is a subset of what `.` matches, a crafted Link header value (attacker-controlled, fetched during webmention discovery/verification) with runs of whitespace could force excessive backtracking. Drop the redundant `\s*` — leading whitespace on each parameter is already trimmed by extractRel's per-parameter `rel` regex. --- .changeset/webmention-fix-polynomial-redos-link-header.md | 5 +++++ packages/webmention/src/html.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/webmention-fix-polynomial-redos-link-header.md diff --git a/.changeset/webmention-fix-polynomial-redos-link-header.md b/.changeset/webmention-fix-polynomial-redos-link-header.md new file mode 100644 index 00000000..9ed6acb2 --- /dev/null +++ b/.changeset/webmention-fix-polynomial-redos-link-header.md @@ -0,0 +1,5 @@ +--- +"@dwk/webmention": patch +--- + +fix(webmention): remove ambiguous quantifier pair in `Link` header parsing regex flagged by CodeQL as a polynomial ReDoS (`js/polynomial-redos`). The redundant `\s*` immediately before `(.*)$` overlapped with what `.` can already match, allowing crafted `Link` header values (attacker-controlled, fetched from a webmention source/target) to force excessive backtracking. Parameter-leading whitespace is still stripped by the per-parameter `rel` regex in `extractRel`, so behavior is unchanged. diff --git a/packages/webmention/src/html.ts b/packages/webmention/src/html.ts index 22c3cf9b..60c9c4c1 100644 --- a/packages/webmention/src/html.ts +++ b/packages/webmention/src/html.ts @@ -37,7 +37,7 @@ export function parseLinkHeader(value: string | null): LinkHeaderEntry[] { } const entries: LinkHeaderEntry[] = []; for (const part of splitLinks(value)) { - const match = /^\s*<([^>]*)>\s*(.*)$/.exec(part); + const match = /^\s*<([^>]*)>(.*)$/.exec(part); if (match === null) { continue; }