From 2d292d07d69c43d9c71d549577fef02c9b46acb3 Mon Sep 17 00:00:00 2001 From: Christopher Pruijsen Date: Fri, 11 Sep 2026 04:54:29 +0100 Subject: [PATCH] Stop unbracketed link destinations at ASCII control characters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The spec forbids U+0000–1F and U+007F in unbracketed destinations. The handwritten scanner only stopped on whitespace, so [a](\x01) became a link. Fixes #127 --- lib/inlines.js | 3 ++- test/test.js | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/inlines.js b/lib/inlines.js index d2907b7a..fc870e13 100644 --- a/lib/inlines.js +++ b/lib/inlines.js @@ -577,7 +577,8 @@ var parseLinkDestination = function() { this.pos += 1; openparens -= 1; } - } else if (reWhitespaceChar.exec(fromCodePoint(c)) !== null) { + } else if (c <= 0x20 || c === 0x7F) { + // ASCII space or control character (U+0000–1F, U+007F) break; } else { this.pos += 1; diff --git a/test/test.js b/test/test.js index 53d40270..94da0c55 100755 --- a/test/test.js +++ b/test/test.js @@ -181,6 +181,31 @@ var cases = [ input: "abc\u0000xyz\u0000\n", expected: "

abc\ufffdxyz\ufffd

\n" }, + { + name: "Issue #127 U+0001 in unbracketed link destination", + input: "[a](\x01)\n", + expected: "

[a](\x01)

\n" + }, + { + name: "Issue #127 U+007F in unbracketed link destination", + input: "[a](\x7f)\n", + expected: "

[a](\x7f)

\n" + }, + { + name: "Issue #127 control character inside unbracketed link destination", + input: "[a](foo\x07bar)\n", + expected: "

[a](foo\x07bar)

\n" + }, + { + name: "Issue #127 U+0001 in unbracketed image destination", + input: "![a](\x01)\n", + expected: "

![a](\x01)

\n" + }, + { + name: "Issue #127 control character in link reference destination", + input: "[foo]: /url\x01\n\n[foo]\n", + expected: "

[foo]: /url\x01

\n

[foo]

\n" + }, { name: "alternate line endings", input: "- a\n- b\r- c\r\n- d",