From c9836d6c48238fbbb4392a5e634465166327233e Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sun, 12 Jul 2026 16:02:20 +0100 Subject: [PATCH 1/2] Add tests demonstrating safe-mode unsafe link over-blocking --- test/test.js | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/test/test.js b/test/test.js index 34d1546d..53d40270 100755 --- a/test/test.js +++ b/test/test.js @@ -314,6 +314,71 @@ for (var j = 0; j < cases.length; j++) { } cursor.write("\n"); +// safe mode +cursor.write("Safe mode:\n"); + +var writerSafe = new commonmark.HtmlRenderer({ safe: true }); + +var safeCases = [ + { + name: "leading javascript: link is blocked", + input: "[link](javascript:alert(1))\n", + expected: "

link

\n" + }, + { + name: "leading JAVASCRIPT: link is blocked", + input: "[link](JAVASCRIPT:alert(1))\n", + expected: "

link

\n" + }, + { + name: "leading vbscript: link is blocked", + input: "[link](vbscript:msgbox(1))\n", + expected: "

link

\n" + }, + { + name: "leading file: link is blocked", + input: "[link](file:///etc/passwd)\n", + expected: "

link

\n" + }, + { + name: "leading data:text/html image is blocked", + input: "![img](data:text/html,x)\n", + expected: '

img

\n' + }, + { + name: "data: image is allowed", + input: "![img](data:image/png;base64,aaaa)\n", + expected: '

img

\n' + }, + { + name: "https link containing data: is allowed", + input: "[link](https://example.com/view?src=data:image/png)\n", + expected: + '

link

\n' + }, + { + name: "https link containing file: is allowed", + input: "[link](https://example.com/download?to=file:report)\n", + expected: + '

link

\n' + }, + { + name: "https image containing vbscript: is allowed", + input: "![img](https://example.com/wiki/vbscript:_basics)\n", + expected: + '

img

\n' + } +]; + +var safe_parse_and_render = function(z) { + return writerSafe.render(reader.parse(z)); +}; + +for (var k = 0; k < safeCases.length; k++) { + pathologicalTest(safeCases[k], results, safe_parse_and_render); +} +cursor.write("\n"); + cursor.write( results.passed.toString() + " tests passed, " + From ac8728eb889246f30cb4eb59a483a395d0c00013 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sun, 12 Jul 2026 16:02:43 +0100 Subject: [PATCH 2/2] Anchor all reUnsafeProtocol alternatives to the start of the URL --- lib/render/html.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/render/html.js b/lib/render/html.js index 4dc2fb58..bef65a66 100644 --- a/lib/render/html.js +++ b/lib/render/html.js @@ -3,7 +3,7 @@ import { escapeXml } from "../common.js"; import Renderer from "./renderer.js"; -var reUnsafeProtocol = /^javascript:|vbscript:|file:|data:/i; +var reUnsafeProtocol = /^(?:javascript|vbscript|file|data):/i; var reSafeDataProtocol = /^data:image\/(?:png|gif|jpeg|webp)/i; var potentiallyUnsafe = function(url) {