<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="/static/style.xsl" type="text/xsl"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title>Most recent entries from all</title>
    <link>https://vulnerability.circl.lu</link>
    <description>Contains only the most 10 recent entries.</description>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>python-feedgen</generator>
    <language>en</language>
    <lastBuildDate>Mon, 28 Sep 2026 09:05:27 +0000</lastBuildDate>
    <item>
      <title>GHSA-crv5-9vww-q3g8 — DOMPurify has a SAFE_FOR_TEMPLATES bypass in RETURN_DOM mode</title>
      <link>https://vulnerability.circl.lu/vuln/ghsa-crv5-9vww-q3g8</link>
      <description>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; npm: dompurify&lt;/p&gt;
&lt;p&gt;## Summary&lt;/p&gt;
&lt;p&gt;| Field | Value |
|:------|:------|
| **Severity** | Medium |
| **Affected** | DOMPurify `main` at [`883ac15`](https://github.com/cure53/DOMPurify/tree/883ac15d47f907cb1a3b5a152fe90c4d8c10f9e6), introduced in v1.0.10 ([`7fc196db`](https://github.com/cure53/DOMPurify/commit/7fc196db0b42a0c360262dba0cc39c9c91bfe1ec)) |&lt;/p&gt;
&lt;p&gt;`SAFE_FOR_TEMPLATES` strips `{{...}}` expressions from untrusted HTML. This works in string mode but not with `RETURN_DOM` or `RETURN_DOM_FRAGMENT`, allowing XSS via template-evaluating frameworks like Vue 2.&lt;/p&gt;
&lt;p&gt;## Technical Details&lt;/p&gt;
&lt;p&gt;DOMPurify strips template expressions in two passes:&lt;/p&gt;
&lt;p&gt;1. **Per-node** — each text node is checked during the tree walk ([`purify.ts:1179-1191`](https://github.com/cure53/DOMPurify/blob/883ac15d47f907cb1a3b5a152fe90c4d8c10f9e6/src/purify.ts#L1179-L1191)):&lt;/p&gt;
&lt;p&gt;```js
// pass #1: runs on every text node during tree walk
if (SAFE_FOR_TEMPLATES &amp;amp;&amp;amp; currentNode.nodeType === NODE_TYPE.text) {
  content = currentNode.textContent;
  content = content.replace(MUSTACHE_EXPR, &amp;#39; &amp;#39;);  // {{...}} -&amp;gt; &amp;#39; &amp;#39;
  content = content.replace(ERB_EXPR, &amp;#39; &amp;#39;);        // &amp;lt;%...%&amp;gt; -&amp;gt; &amp;#39; &amp;#39;
  content = content.replace(TMPLIT_EXPR, &amp;#39; &amp;#39;);      // ${...  -&amp;gt; &amp;#39; &amp;#39;
  currentNode.textContent = content;
}
```&lt;/p&gt;
&lt;p&gt;2. **Final string scrub** — after serialization, the full HTML string is scrubbed again ([`purify.ts:1679-1683`](https://github.com/cure53/DOMPurify/blob/883ac15d47f907cb1a3b5a152fe90c4d8c10f9e6/src/purify.ts#L1679-L1683)). This is the safety net that catches expr…&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; npm: dompurify&lt;/p&gt;
&lt;p&gt;## Summary&lt;/p&gt;
&lt;p&gt;| Field | Value |
|:------|:------|
| **Severity** | Medium |
| **Affected** | DOMPurify `main` at [`883ac15`](https://github.com/cure53/DOMPurify/tree/883ac15d47f907cb1a3b5a152fe90c4d8c10f9e6), introduced in v1.0.10 ([`7fc196db`](https://github.com/cure53/DOMPurify/commit/7fc196db0b42a0c360262dba0cc39c9c91bfe1ec)) |&lt;/p&gt;
&lt;p&gt;`SAFE_FOR_TEMPLATES` strips `{{...}}` expressions from untrusted HTML. This works in string mode but not with `RETURN_DOM` or `RETURN_DOM_FRAGMENT`, allowing XSS via template-evaluating frameworks like Vue 2.&lt;/p&gt;
&lt;p&gt;## Technical Details&lt;/p&gt;
&lt;p&gt;DOMPurify strips template expressions in two passes:&lt;/p&gt;
&lt;p&gt;1. **Per-node** — each text node is checked during the tree walk ([`purify.ts:1179-1191`](https://github.com/cure53/DOMPurify/blob/883ac15d47f907cb1a3b5a152fe90c4d8c10f9e6/src/purify.ts#L1179-L1191)):&lt;/p&gt;
&lt;p&gt;```js
// pass #1: runs on every text node during tree walk
if (SAFE_FOR_TEMPLATES &amp;amp;&amp;amp; currentNode.nodeType === NODE_TYPE.text) {
  content = currentNode.textContent;
  content = content.replace(MUSTACHE_EXPR, &amp;#39; &amp;#39;);  // {{...}} -&amp;gt; &amp;#39; &amp;#39;
  content = content.replace(ERB_EXPR, &amp;#39; &amp;#39;);        // &amp;lt;%...%&amp;gt; -&amp;gt; &amp;#39; &amp;#39;
  content = content.replace(TMPLIT_EXPR, &amp;#39; &amp;#39;);      // ${...  -&amp;gt; &amp;#39; &amp;#39;
  currentNode.textContent = content;
}
```&lt;/p&gt;
&lt;p&gt;2. **Final string scrub** — after serialization, the full HTML string is scrubbed again ([`purify.ts:1679-1683`](https://github.com/cure53/DOMPurify/blob/883ac15d47f907cb1a3b5a152fe90c4d8c10f9e6/src/purify.ts#L1679-L1683)). This is the safety net that catches expr…&lt;/p&gt;</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/vuln/ghsa-crv5-9vww-q3g8</guid>
    </item>
  </channel>
</rss>
