GitHub Advisoryadvisory · npm
GHSA-x9fj-57fh-c8wq Marko: XSS via case-insensitive script/style closing tag bypass in runtime HTML escaping
MEDIUM
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