Skip to content

fix(markdown): block /\ protocol-relative redirect in safeUrl - #47

Closed
zqxuii wants to merge 1 commit into
moshcoder:masterfrom
zqxuii:fix/md-backslash-redirect
Closed

fix(markdown): block /\ protocol-relative redirect in safeUrl#47
zqxuii wants to merge 1 commit into
moshcoder:masterfrom
zqxuii:fix/md-backslash-redirect

Conversation

@zqxuii

@zqxuii zqxuii commented Jul 22, 2026

Copy link
Copy Markdown

What

safeUrl allows /path but blocks //host to keep links on-site. It misses the backslash form: browsers normalise \ to /, so href="/\evil.com" resolves to //evil.com — an off-site (open) redirect.

Why it matters

renderMarkdown renders owner/content-block markdown on tenant pages. \ is not HTML-escaped and is not whitespace, so the link/image regex captures it and it reaches safeUrl. Verified:

  • [click](/\evil.com) -> <a href="/\evil.com"> (browser -> //evil.com)
  • ![x](/\evil.com) -> <img src="/\evil.com">
  • [ok](//evil.com) is correctly blocked; the \ form slipped past the same guard.

Fix

Reject a leading /\ as well as //: /^\/(?![/\\])/. Legit /path, https:, mailto: and #anchor are unchanged.

Tests

Added tests/markdown.test.mjs: backslash link + image blocked, // still blocked, legit relative/absolute still work, javascript: still blocked. node --test tests/markdown.test.mjs passes; no other tests affected.

safeUrl allowed "/path" but blocked "//host" to keep links on-site. It missed
the backslash form: browsers normalise \ to /, so href="/\evil.com" resolves to
"//evil.com" — an off-site redirect from user-authored content blocks. \ isn't
HTML-escaped and isn't matched by the link regex's \s, so it reaches safeUrl.
Reject a leading /\ as well as //; add regression tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant