Skip to content

fix: escape HTML entities in link href and image src attributes - #4065

Closed
madebysaira wants to merge 1 commit into
markedjs:masterfrom
madebysaira:fix/html-entity-escape-link-href
Closed

fix: escape HTML entities in link href and image src attributes#4065
madebysaira wants to merge 1 commit into
markedjs:masterfrom
madebysaira:fix/html-entity-escape-link-href

Conversation

@madebysaira

Copy link
Copy Markdown

Summary

Fixes #4052

The renderer wrote cleanUrl(href) directly into href/ attributes without escaping & to &. This caused silent link-target corruption for URLs containing valid HTML entity sequences (<, &, ©, etc.).

The bug

marked('<https://example.com/?x=1&lt;2>')
// Actual:   href="...?x=1&lt;2"    (browser decodes to ...?x=1<2 — WRONG)
// Expected: href="...?x=1&amp;lt;2" (browser decodes to ...?x=1&lt;2 — CORRECT)

Any URL containing a valid entity sequence silently changes the link target. This also affects CommonMark example 595.

Root cause

Two issues:

  1. RenderercleanUrl() runs encodeURI() which never encodes &, so the raw & reaches the HTML attribute unescaped.
  2. Tokenizer — inline link destinations ([text](url)) kept HTML entities literal (&amp; stayed as &amp;), which is correct per CommonMark, but the renderer never escaped them on output.

Fix (2 parts)

  1. Tokenizer (src/Tokenizer.ts) — Decode HTML entities in inline link destinations before rendering, per CommonMark spec (entity references are recognized in link destinations but not in autolinks).

  2. Renderer (src/Renderer.ts) — Escape &&amp; in href/ attributes after cleanUrl(), ensuring valid HTML output.

  3. Helper (src/helpers.ts) — Added decodeHtmlEntities() function for named/numeric character reference decoding.

Test results

  • ✅ All 1783 CommonMark spec tests pass (no regressions)
  • ✅ All 196 unit tests pass (including 5 new regression tests)
  • ✅ CommonMark example 595 now produces correct output

Regression tests added

5 new test cases in test/unit/marked.test.js covering:

  • Autolink with & (CommonMark example 595)
  • Inline link with &amp; entity
  • Plain autolink URL with &
  • Autolink with &lt; entity
  • Image with & in src

The renderer wrote cleanUrl(href) directly into href/src attributes
without escaping & to &amp;. This caused silent link-target corruption
for URLs containing valid HTML entity sequences (e.g. &lt;, &amp;,
&copy;). A browser decodes these inside attributes, so the link
pointed to a different URL than was written.

The fix has two parts:

1. Tokenizer: decode HTML entities in inline link destinations before
   rendering, per CommonMark spec (entity references are recognized in
   link destinations but not in autolinks).

2. Renderer: escape & to &amp; in href/src attributes after cleanUrl,
   ensuring the output is valid HTML that browsers interpret correctly.

Added decodeHtmlEntities helper and 5 regression tests covering
autolinks, inline links, images, and entity sequences.

Fixes markedjs#4052
@vercel

vercel Bot commented Aug 20, 2026

Copy link
Copy Markdown

@madebysaira is attempting to deploy a commit to the MarkedJS Team on Vercel.

A member of the Team first needs to authorize it.

@UziTech

UziTech commented Aug 20, 2026

Copy link
Copy Markdown
Member

This is already being fixed in #4053

@UziTech UziTech closed this Aug 20, 2026
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.

& not HTML-escaped in link/autolink href, silently changing the link target

2 participants