fix(ui): keep local file markdown links inert

This commit is contained in:
Bryan Tegomoh
2026-05-25 12:51:35 -05:00
committed by Peter Steinberger
parent 342bde2af6
commit fc2d2d595c
2 changed files with 25 additions and 0 deletions

View File

@@ -569,6 +569,20 @@ PY
const html = toSanitizedMarkdownHtml("[click](file:///etc/passwd)");
expect(html).toBe("<p><a>click</a></p>\n");
});
it("strips href from host-local absolute file paths", () => {
const html = toSanitizedMarkdownHtml(
"[report.docx](/Users/test/.openclaw/data/skills/output/report.docx)",
);
expect(html).toBe("<p><a>report.docx</a></p>\n");
});
it("keeps app-relative links navigable", () => {
const html = toSanitizedMarkdownHtml("[usage](/usage)");
expect(html).toBe(
'<p><a href="/usage" rel="noreferrer noopener" target="_blank">usage</a></p>\n',
);
});
});
describe("ReDoS protection", () => {

View File

@@ -84,6 +84,8 @@ const MARKDOWN_PARSE_LIMIT = 40_000;
const MARKDOWN_CACHE_LIMIT = 200;
const MARKDOWN_CACHE_MAX_CHARS = 50_000;
const INLINE_DATA_IMAGE_RE = /^data:image\/[a-z0-9.+-]+;base64,/i;
const HOST_LOCAL_FILE_HREF_RE =
/^(?:~\/|\/(?:Users|home|tmp|private\/tmp|var\/folders|private\/var\/folders)\/|\/[A-Za-z]:\/|[A-Za-z]:[\\/])/;
const markdownCache = new Map<string, string>();
const TAIL_LINK_BLUR_CLASS = "chat-link-tail-blur";
@@ -135,6 +137,10 @@ function shouldRenderCodeBlockCopy(env: unknown): boolean {
return (env as Partial<MarkdownRenderEnv> | undefined)?.codeBlockChrome !== "none";
}
function isHostLocalFileHref(href: string): boolean {
return HOST_LOCAL_FILE_HREF_RE.test(href.trim());
}
function installHooks() {
if (hooksInstalled) {
return;
@@ -150,6 +156,11 @@ function installHooks() {
return;
}
if (isHostLocalFileHref(href)) {
node.removeAttribute("href");
return;
}
// Block dangerous URL schemes (javascript:, data:, vbscript:, etc.)
try {
const url = new URL(href, window.location.href);