testMarkdownLinksHaveSafeSchemes
Markdown's links are made only to http(s), mailto and relative addresses; any other scheme is left as text.
import type { Codebase } from "#codebase/tcmts/cli/codebase"; import { markdownHtml } from "#codebase/tcmts/share"; import assert from "node:assert/strict"; export const testMarkdownLinksHaveSafeSchemes = () => { const cb = { store: { pathsOf: () => [] } } as unknown as Codebase; const html = (md: string) => markdownHtml(cb, md); for (const bad of [ "javascript:alert(1)", "JaVaScRiPt:alert(1)", "java\tscript:alert(1)", " javascript:alert(1)", "data:text/html,<b>x</b>", "vbscript:x", ]) { const out = html(`[click](<${bad}>)`); assert.doesNotMatch(out, /<a /, `${JSON.stringify(bad)}: ${out}`); assert.match(out, /click/); } for (const ok of [ "https://example.com/x", "http://example.com", "mailto:a@example.com", "/docs/x", "#anchor", "notes.md", ]) assert.match(html(`[go](${ok})`), /<a href="[^"]+">go<\/a>/, ok); }