GitHub Advisoryadvisory · npm

GHSA-x9fj-57fh-c8wq Marko: XSS via case-insensitive script/style closing tag bypass in runtime HTML escaping

MEDIUM Published 2026-04-22 Modified 2026-05-13 Official page ↗
Aliases
CVE-2026-41591
Ecosystem
npm
Packages
marko, @marko/runtime-tags
Severity
Moderate
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N
Weaknesses
CWE-79
Reviewed
2026-04-22

Affected packages

• npm marko: < 5.38.36 → fixed in 5.38.36 • npm @marko/runtime-tags: < 6.0.164 → fixed in 6.0.164

Description

Summary When dynamic text is interpolated into a `` or `` tag the Marko runtime failed to prevent tag breakout when the closing tag used non-lowercase casing. An attacker able to place input inside a `` or `` block could break out of the tag with ``, ``, etc. and inject arbitrary HTML/JavaScript, resulting in cross-site scripting. Details The affected helpers used case-sensitive regular expressions to detect attempts at closing the surrounding tag: ```js // packages/runtime-tags/src/html/content.ts const unsafeScriptReg = /`, ``, or `` were not matched by these regexes and passed through the helpers unchanged. A browser rendering the output treats the mixed-case end tag as a valid closing tag, terminating the script or style context, and then parses anything that follows as HTML. The Marko compiler routes interpolated values inside `` and `` tags through these helpers automatically (see `native-tag.ts:1080-1085`), so application code following the framework's conventions had no way to detect or compensate for the gap. PoC ```marko $ const userCode = "alert(1)//"; const data = ${JSON.stringify(userCode)}; ``` Would yield the following: ```html const data = "alert(1)//"; ``` Which is then parsed in any WHATWG-compliant browser as: ```html const data = " alert(1)//"; ``` Impact Cross-site scripting. Any Marko template that explicitly interpolates untrusted data inside a `` or `` block is affected. Stored XSS is trivial if the value originates from any persisted user input (username, profile bio, comment body, etc.) that is later embedded in a script tag during rendering. Exploitation yields arbitrary JavaScript execution in the victim's browser, enabling session token theft, account takeover, and arbitrary actions as the victim. Since the internal `_escape_script` and `_escape_style` helpers are the framework's designated defense against script/style tag breakout, applications following standard Marko patterns had no obvious reason to add a second layer of sanitization. This does not affect scripts or hydration state serialized by Marko itself — only templates that explicitly interpolate untrusted values inside a or tag. Patch Commit `19d4b37d0` — `fix: html script, style, and comment escaping`. ```diff • const unsafeScriptReg = /` or `` tag — e.g. normalize `</script`, `</style`, and their mixed-case variants before interpolation, or avoid direct interpolation of untrusted values inside these tags entirely.

Related

Alias · CVE (1)

  • CVE-2026-41591 Marko is a declarative, HTML-based language for building web apps. vulnerability

Weakness · CWE (1)

  • CWE-79 Improper Neutralization of Input During Web Page Generation weakness

References