CVE-2026-113661: ApostropheCMS: Incomplete CVE-2026-53606: `meta http-equiv=refresh` `content` still ships `javascript:` / `data:` URLs
Summary
CVE-2026-53606 expanded allowedSchemesAppliedToAttributes so named URL attributes (action, formaction, data, poster, background, later ping, xlink:href, …) go through naughtyHref(). A URL nested inside meta content (http-equiv=refresh) is not an attribute name on that list, so the embedded destination is never scheme-checked.
Default allowedTags still omit meta. Same non-default integrator config as 53606: allow meta plus http-equiv / content.
On 2.17.7:
text sanitizeHtml( '<meta http-equiv="refresh" content="0;url=javascript:alert(1)">', { allowedTags: ['meta'], allowedAttributes: { meta: ['http-equiv', 'content'] } } ) // => <meta http-equiv="refresh" content="0;url=javascript:alert(1)" />
data:text/html,… and arbitrary https: destinations also survive. formaction="javascript:…" (53606) is stripped.
Please Request CVE. Credit: Finder + Reporter (adrbogacz).
Details
naughtyHref() only runs when the attribute name is in allowedSchemesAppliedToAttributes (index.js ~385). Refresh URLs live in a content value of the form 0;url=…, so the gate never fires. Adding content to that list wholesale would break ordinary meta content (description, viewport).
Fix: when http-equiv is refresh (case-insensitive), parse the ; url= destination and run naughtyHref('meta', url). Drop content (or the tag) if the URL is rejected. Leave other meta content values alone.
PoC
Local sanitize-html@2.17.7. Output inspection only:
text node -e ' const sanitize = require("sanitize-html"); const opts = { allowedTags: ["meta"], allowedAttributes: { meta: ["http-equiv", "content"] } }; for (const html of [ "<meta http-equiv=\"refresh\" content=\"0;url=javascript:alert(1)\">", "<meta http-equiv=\"refresh\" content=\"0;url=data:text/html,aaa\">", "<form><button formaction=\"javascript:alert(1)\">x</button></form>", ]) { console.log(html, "=>", sanitize(html, html.includes("meta") ? opts : { allowedTags: ["form","button"], allowedAttributes: { button: ["formaction"] } })); } '
Expected: refresh javascript: / data: remain; 53606 formaction is removed. Do not attach a browser hang or stored-XSS page.
Impact
An integrator who allowed meta + content expecting allowedSchemes to apply (the 53606 configuration pattern) still emits a refresh to javascript:, data:, or an attacker https: URL. Stored XSS / open redirect for viewers of that HTML. Default config is not affected.
Other sources
ApostropheCMS is an open-source Node.js content management system, and sanitize-html provides a simple HTML sanitizer with a clear API. Prior to sanitize-html 2.18.0, a non-default configuration that allows meta refresh elements and their http-equiv and content attributes can retain unsafe script or redirect destinations embedded in the refresh content value. This issue is fixed in sanitize-html 2.18.0.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/sanitize-htmlto a version that resolves this vulnerability.Fixed in 2.18.0 - Upgrade
Upgrade
sanitize-htmlto a version that resolves this vulnerability.Fixed in 2.18.0
Event History
Frequently Asked Questions
Which deployments are affected?
Affected deployments use sanitize-html before version 2.18.0 and have a non-default configuration that permits meta refresh elements along with their http-equiv and content attributes. Default configurations are not identified as affected by the provided information.
What must an attacker be able to do to exploit this issue?
An attacker needs the ability to supply HTML that is processed by the affected sanitizer configuration, and a user must interact with the resulting content. The unsafe destination is embedded in the meta refresh content value and may use javascript: or data: URLs.
What should be done if immediate remediation is needed?
Upgrade sanitize-html to version 2.18.0. Until then, avoid allowing meta refresh elements or their http-equiv and content attributes in sanitizer configuration.
How can I determine whether my application is exposed?
Check whether the application uses a sanitize-html version earlier than 2.18.0 and whether its configuration explicitly allows meta refresh plus the http-equiv and content attributes. Review sanitized user-controlled HTML for retained meta refresh content values containing javascript: or data: destinations.