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

2 participants