PT-2026-120329 · Npm · Sanitize-Html
تاريخ النشر
2026-10-20
·
تاريخ التحديث
2026-10-20
CVSS v4.0
5.3
متوسطة
| المتجه | AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N |
Summary
sanitize-html discards the content of every element in nonTextTags. It delimits that region
using htmlparser2's close events, and ignores the isImplied flag htmlparser2 passes it. Closing a
still-open ancestor from inside a <noscript> makes htmlparser2 unwind its stack past the
noscript; the synthetic implied close it emits on the way ends the discard region early, and
everything after it is treated as ordinary body content.A browser with scripting enabled parses
<noscript> content as raw text, so the same markup
renders as inert text there. The sanitizer therefore emits elements the page itself would not have.Reproduction
js
const sanitizeHtml = require("sanitize-html");
sanitizeHtml('<div><noscript></div><img src="http://evil.test/t.gif"></noscript>', {
allowedTags: ["div", "img"],
allowedAttributes: { img: ["src"] },
nonTextTags: ["script", "style", "textarea", "option", "noscript"],
});
// => '<div></div><img src="http://evil.test/t.gif" />'Chrome, given the same input, renders no
<img> — the whole payload is raw text inside the
unclosed <noscript>. Verified with Playwright, srcdoc into an iframe so the scripting flag is on.A
<![CDATA[ variant hides the opening tag from the parser entirely and has the same effect:<p>Hi</p><![CDATA[ x > <noscript>]]><a href="…">Reset your password</a><img src="…beacon.gif"></noscript>htmlparser2 runs a CDATA token to
]]>; Chrome ends a bogus comment at the first >, so the
<noscript> after it is real to the browser and invisible to the parser.Where the behaviour is
index.js::154—nonTextTagsArray(the default list,['script','style','textarea','option','xmp']).:638—onclosetag: function (name, isImplied)— receives the flag.:644—skipTextDepth--— decrements without consultingisImplied.
Suggested fix
Do not end a discard region on an implied close. htmlparser2 already distinguishes them; the flag
is passed and discarded. Something close to:
js
onclosetag: function (name, isImplied) {
if (skipText) {
if (isImplied) return; // an implied close must not end the region
skipTextDepth--;
…إصلاح
XSS
وجدت خطأً في الوصف؟ لديك ما تضيفه؟ لا تتردد في مراسلتنا 👾
تصنيف نقاط الضعف
المعرّفات ذات الصلة
المنتجات المتأثرة
Sanitize-Html