{"id":"CVE-2026-116804","aliases":["CLSA-2026-1793100794","CLSA-2026-1793100979","CLSA-2026-1793101079","CLSA-2026-1793101206","CLSA-2026-1793101291","CLSA-2026-1793101437","CLSA-2026-1793101539","CLSA-2026-1793101597","CLSA-2026-1793101938","CLSA-2026-1793102164","CLSA-2026-1793102424","CLSA-2026-1793120002","CLSA-2026-1793348733","CLSA-2026-1793348774","CLSA-2026-1793348834","CLSA-2026-1793348929","CLSA-2026-1793349051","CLSA-2026-1793349529","CLSA-2026-1793349839","CLSA-2026-1793350195","DEBIAN-CVE-2026-116804","EUVD-2026-110512","GHSA-6vxf-252m-8g79","GHSA-cg2g-xh64-v4q7","ROOT-APP-NPM-GHSA-cg2g-xh64-v4q7","UBUNTU-CVE-2026-116804"],"status":"published","title":"DOMPurify from 3.4.4 before 3.4.17 SAFE_FOR_TEMPLATES Bypass via Shadow Root Content","description":"DOMPurify from 3.4.4 before 3.4.17 contains a SAFE_FOR_TEMPLATES bypass that lets attackers preserve template expressions in attached shadow roots when using RETURN_DOM, RETURN_DOM_FRAGMENT, or IN_PLACE modes. Attackers can split expressions across text nodes separated by disallowed elements, which merge after removal and are evaluated by downstream template engines for cross-site scripting.","severity":{"version":"4.0","score":5.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-11","score":0.00178,"percentile":0.07491,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-79"],"published":"2026-10-22T16:25:31Z","modified":"2026-11-04T02:31:04Z","fixes":[{"ecosystem":"npm","package":"dompurify","fixed_in":["3.4.17"],"sources":["ghsa","osv"]},{"ecosystem":"TuxCare:npm","package":"dompurify","fixed_in":["3.4.16-tuxcare.1","3.4.8-tuxcare.8","3.4.9-tuxcare.6","3.4.10-tuxcare.6","3.4.5-tuxcare.6","3.4.12-tuxcare.4","3.4.14-tuxcare.5","3.4.11-tuxcare.6","3.4.15-tuxcare.4"],"sources":["osv"]},{"ecosystem":"Debian:14","package":"node-dompurify","fixed_in":["3.4.17+dfsg-1"],"sources":["osv"]},{"ecosystem":"Root:npm","package":"dompurify","fixed_in":["3.4.11-aikido.1","3.4.13-aikido.1","3.4.14-aikido.1","3.4.15-aikido.1","3.4.15-aikido.2","3.4.16-aikido.1","3.4.16-aikido.2"],"sources":["osv"]},{"ecosystem":"Root:npm","package":"@rootio/dompurify","fixed_in":["3.4.11-root.io.1","3.4.13-root.io.1","3.4.14-root.io.1","3.4.15-root.io.1","3.4.15-root.io.2","3.4.16-root.io.1","3.4.16-root.io.2"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.4"},{"last_affected":"3.4.16"},{"fixed":"3.4.17"}]}]},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.5-tuxcare.0"},{"fixed":"3.4.5-tuxcare.5"}]}],"versions":["3.4.5","3.4.5-tuxcare.1","3.4.5-tuxcare.2","3.4.5-tuxcare.3","3.4.5-tuxcare.4"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.8-tuxcare.0"},{"fixed":"3.4.8-tuxcare.7"}]}],"versions":["3.4.8","3.4.8-tuxcare.1","3.4.8-tuxcare.2","3.4.8-tuxcare.3","3.4.8-tuxcare.4","3.4.8-tuxcare.5","3.4.8-tuxcare.6"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.13-tuxcare.0"},{"fixed":"3.4.13-tuxcare.3"}]}],"versions":["3.4.13","3.4.13-tuxcare.1","3.4.13-tuxcare.2"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.11-tuxcare.0"},{"fixed":"3.4.11-tuxcare.5"}]}],"versions":["3.4.11","3.4.11-tuxcare.1","3.4.11-tuxcare.2","3.4.11-tuxcare.3","3.4.11-tuxcare.4"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.6-tuxcare.0"},{"fixed":"3.4.6-tuxcare.5"}]}],"versions":["3.4.6","3.4.6-tuxcare.1","3.4.6-tuxcare.2","3.4.6-tuxcare.3","3.4.6-tuxcare.4"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.7-tuxcare.0"},{"fixed":"3.4.7-tuxcare.5"}]}],"versions":["3.4.7","3.4.7-tuxcare.1","3.4.7-tuxcare.2","3.4.7-tuxcare.3","3.4.7-tuxcare.4"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.14-tuxcare.0"},{"fixed":"3.4.14-tuxcare.4"}]}],"versions":["3.4.14","3.4.14-tuxcare.1","3.4.14-tuxcare.2","3.4.14-tuxcare.3"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.9-tuxcare.0"},{"fixed":"3.4.9-tuxcare.5"}]}],"versions":["3.4.9","3.4.9-tuxcare.1","3.4.9-tuxcare.2","3.4.9-tuxcare.3","3.4.9-tuxcare.4"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.10-tuxcare.0"},{"fixed":"3.4.10-tuxcare.5"}]}],"versions":["3.4.10","3.4.10-tuxcare.1","3.4.10-tuxcare.2","3.4.10-tuxcare.3","3.4.10-tuxcare.4"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.12-tuxcare.0"},{"fixed":"3.4.12-tuxcare.3"}]}],"versions":["3.4.12","3.4.12-tuxcare.1","3.4.12-tuxcare.2"],"bundled":3},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.15-tuxcare.0"},{"fixed":"3.4.15-tuxcare.3"}]}],"versions":["3.4.15","3.4.15-tuxcare.1","3.4.15-tuxcare.2"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.16-tuxcare.0"},{"fixed":"3.4.16-tuxcare.1"}]}],"versions":["3.4.16"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.8-tuxcare.0"},{"fixed":"3.4.8-tuxcare.8"}]}],"versions":["3.4.8","3.4.8-tuxcare.1","3.4.8-tuxcare.2","3.4.8-tuxcare.3","3.4.8-tuxcare.4","3.4.8-tuxcare.5","3.4.8-tuxcare.6","3.4.8-tuxcare.7"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.9-tuxcare.0"},{"fixed":"3.4.9-tuxcare.6"}]}],"versions":["3.4.9","3.4.9-tuxcare.1","3.4.9-tuxcare.2","3.4.9-tuxcare.3","3.4.9-tuxcare.4","3.4.9-tuxcare.5"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.10-tuxcare.0"},{"fixed":"3.4.10-tuxcare.6"}]}],"versions":["3.4.10","3.4.10-tuxcare.1","3.4.10-tuxcare.2","3.4.10-tuxcare.3","3.4.10-tuxcare.4","3.4.10-tuxcare.5"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.5-tuxcare.0"},{"fixed":"3.4.5-tuxcare.6"}]}],"versions":["3.4.5","3.4.5-tuxcare.1","3.4.5-tuxcare.2","3.4.5-tuxcare.3","3.4.5-tuxcare.4","3.4.5-tuxcare.5"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.12-tuxcare.0"},{"fixed":"3.4.12-tuxcare.4"}]}],"versions":["3.4.12","3.4.12-tuxcare.1","3.4.12-tuxcare.2","3.4.12-tuxcare.3"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.14-tuxcare.0"},{"fixed":"3.4.14-tuxcare.5"}]}],"versions":["3.4.14","3.4.14-tuxcare.1","3.4.14-tuxcare.2","3.4.14-tuxcare.3","3.4.14-tuxcare.4"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.11-tuxcare.0"},{"fixed":"3.4.11-tuxcare.6"}]}],"versions":["3.4.11","3.4.11-tuxcare.1","3.4.11-tuxcare.2","3.4.11-tuxcare.3","3.4.11-tuxcare.4","3.4.11-tuxcare.5"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.4.15-tuxcare.0"},{"fixed":"3.4.15-tuxcare.4"}]}],"versions":["3.4.15","3.4.15-tuxcare.1","3.4.15-tuxcare.2","3.4.15-tuxcare.3"]},{"source":"osv","ecosystem":"Debian:14","package":"node-dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.4.17+dfsg-1"}]}],"versions":["3.1.7+dfsg+~3.0.5-2","3.2.5+dfsg-1","3.3.2+dfsg-1","3.3.3+dfsg-1","3.3.3+dfsg-2","3.4.1+dfsg-1","3.4.12+dfsg-1","3.4.13+dfsg-1","3.4.13+dfsg-2","3.4.16+dfsg-1","3.4.2+dfsg-1","3.4.5+dfsg-1"]},{"source":"osv","ecosystem":"npm","package":"dompurify","ranges":[{"type":"SEMVER","events":[{"introduced":"3.4.4"},{"fixed":"3.4.17"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.4.11-aikido.1"},{"fixed":"3.4.13-aikido.1"},{"fixed":"3.4.14-aikido.1"},{"fixed":"3.4.15-aikido.1"},{"fixed":"3.4.15-aikido.2"},{"fixed":"3.4.16-aikido.1"},{"fixed":"3.4.16-aikido.2"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"@rootio/dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.4.11-root.io.1"},{"fixed":"3.4.13-root.io.1"},{"fixed":"3.4.14-root.io.1"},{"fixed":"3.4.15-root.io.1"},{"fixed":"3.4.15-root.io.2"},{"fixed":"3.4.16-root.io.1"},{"fixed":"3.4.16-root.io.2"}]}]},{"source":"osv","ecosystem":"Ubuntu:22.04:LTS","package":"node-dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.3.0+dfsg-2","2.3.3+dfsg-1"]},{"source":"osv","ecosystem":"Ubuntu:24.04:LTS","package":"node-dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.4.1+dfsg+~2.4.0-1","3.0.9+dfsg+~3.0.5-1"]},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"node-dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.3.3+dfsg-1","3.4.2+dfsg-1","3.4.5+dfsg-1","3.4.12+dfsg-1","3.4.13+dfsg-1","3.4.13+dfsg-2"]},{"source":"osv","ecosystem":"Ubuntu:26.04:LTS","package":"node-dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.1.7+dfsg+~3.0.5-2","3.3.3+dfsg-1"]}],"products":[{"vendor":"cure53","product":"dompurify"}],"references":[{"url":"https://github.com/cure53/DOMPurify/security/advisories/GHSA-cg2g-xh64-v4q7","tags":["vendor-advisory","exploit","advisory","web","report"]},{"url":"https://www.vulncheck.com/advisories/dompurify-from-3.4.4-before-3.4.17-safe-for-templates-bypass-via-shadow-root-content","tags":["third-party-advisory","advisory","report"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-116804","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-6vxf-252m-8g79"},{"url":"https://github.com/cure53/DOMPurify/pull/1672","tags":["web"]},{"url":"https://github.com/cure53/DOMPurify/commit/a77a3e78b59f72fa4d1c83f22e121ad9cc7d3575","tags":["web"]},{"url":"https://github.com/cure53/DOMPurify/releases/tag/3.4.17","tags":["web"]},{"url":"https://github.com/advisories/GHSA-cg2g-xh64-v4q7"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/116xxx/CVE-2026-116804.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-116804","tags":["advisory"]},{"url":"https://github.com/cure53/DOMPurify","tags":["package"]},{"url":"https://ubuntu.com/security/CVE-2026-116804","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-116804","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2026-116804","title":"DOMPurify from 3.4.4 before 3.4.17 SAFE_FOR_TEMPLATES Bypass via Shadow Root Content","description":"DOMPurify from 3.4.4 before 3.4.17 contains a SAFE_FOR_TEMPLATES bypass that lets attackers preserve template expressions in attached shadow roots when using RETURN_DOM, RETURN_DOM_FRAGMENT, or IN_PLACE modes. Attackers can split expressions across text nodes separated by disallowed elements, which merge after removal and are evaluated by downstream template engines for cross-site scripting.","status":"published","published":"2026-10-26T23:05:35.85Z","modified":"2026-11-02T18:41:37.395Z","cvss":[{"version":"4.0","score":5.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N","level":"medium","assessor":"cna"},{"version":"3.1","score":6.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T19:47:06.831391Z"}],"euvd":[{"id":"EUVD-2026-110512","description":"DOMPurify from 3.4.4 before 3.4.17 contains a SAFE_FOR_TEMPLATES bypass that lets attackers preserve template expressions in attached shadow roots when using RETURN_DOM, RETURN_DOM_FRAGMENT, or IN_PLACE modes. Attackers can split expressions across text nodes separated by disallowed elements, which merge after removal and are evaluated by downstream template engines for cross-site scripting.","status":"published","published":"2026-10-26T23:05:35Z","modified":"2026-11-02T18:41:37Z","cvss":[{"version":"4.0","score":5.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N","level":"medium"}],"updated_at":"2026-11-03T05:08:38.713005Z"}],"ghsa":[{"id":"GHSA-6vxf-252m-8g79","title":"DOMPurify from 3.4.4 before 3.4.17 contains a SAFE_FOR_TEMPLATES bypass that lets attackers...","description":"DOMPurify from 3.4.4 before 3.4.17 contains a SAFE_FOR_TEMPLATES bypass that lets attackers preserve template expressions in attached shadow roots when using RETURN_DOM, RETURN_DOM_FRAGMENT, or IN_PLACE modes. Attackers can split expressions across text nodes separated by disallowed elements, which merge after removal and are evaluated by downstream template engines for cross-site scripting.","status":"published","published":"2026-10-27T00:32:51Z","modified":"2026-10-27T00:32:59Z","cvss":[{"version":"4.0","score":5.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"medium"},{"version":"3.1","score":6.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T15:14:27.349207Z"},{"id":"GHSA-cg2g-xh64-v4q7","title":"DOMPurify SAFE_FOR_TEMPLATES bypass: split template expressions survive in attached shadow root content on DOM output modes","description":"## Summary\n\nWhen DOMPurify is configured with `SAFE_FOR_TEMPLATES: true` together with a DOM-returning mode (`RETURN_DOM: true`, `RETURN_DOM_FRAGMENT: true`, or `IN_PLACE: true`), template expressions such as `{{...}}`, `${...}`, and `\u003c%...%\u003e` survive sanitization inside the text content of an attached shadow root. The post-walk safety net `_scrubTemplateExpressions` (`src/purify.ts:1717`) was extended to recurse into `\u003ctemplate\u003e.content`, but it never recurses into attached shadow roots. An attacker who can supply a DOM node carrying a shadow root (the `IN_PLACE` and shadow-aware `RETURN_DOM` surfaces) can split an expression across text nodes separated by disallowed elements; after those elements are removed the fragments become adjacent and serialize into a complete expression that a downstream template engine will evaluate.\n\n## Root Cause\n\n`SAFE_FOR_TEMPLATES` neutralizes template expressions through two mechanisms: a per-text-node strip during the main walk (`_stripTemplateExpressions`, applied in `_sanitizeElements` at `src/purify.ts:2246`), and a final post-walk pass (`_scrubTemplateExpressions`, `src/purify.ts:1717`) that normalizes adjacent text nodes and re-strips expressions that only form after merging. The per-node strip cannot catch an expression that is split into individual fragments, because each fragment fails the delimiter regexes. The post-walk pass is the only mechanism that would catch the merged form, but it is structurally unable to reach shadow root content.\n\n```text\n_scrubTemplateExpressions (src/purify.ts:1717-1751):\n  - node.normalize() at line 1718 does not merge text nodes inside shadow roots (DOM spec).\n  - NodeIterator at lines 1723-1731 does not descend into shadow trees (DOM spec).\n  - Explicit recursion at lines 1743-1750 enters \u003ctemplate\u003e.content only, via\n    querySelectorAll('template'); there is no equivalent recursion into attached\n    shadow roots.\nShadow roots are sanitized earlier by _sanitizeShadowDOM (src/purify.ts:2710), which\napplies the per-node strip but never performs the post-walk normalize-and-rescrub.\n```\n\nShadow root text nodes are therefore sanitized only per-node and never re-examined as a merged unit.\n\n## Impact\n\nAn attacker who controls DOM-node input containing an attached shadow root can inject template expressions that survive sanitization and are later evaluated by the application's template engine. In client-side contexts this yields cross-site scripting; in a server-side template context it can escalate to template injection. Exploitation requires non-default application configuration: the application must enable `SAFE_FOR_TEMPLATES` and a DOM-returning mode, pass a DOM node that already has an attached shadow root, and feed the sanitized shadow root content into a template evaluator. The shadow root does not have to be built programmatically with `attachShadow`: in engines that support declarative shadow DOM, attacker-supplied markup containing `\u003ctemplate shadowrootmode=\"open\"\u003e` parsed through `setHTMLUnsafe` or `Document.parseHTMLUnsafe` produces the same attached shadow root, so a plain HTML string reaches the gap once the application is configured this way. Demonstrated capability is injection of a complete, attacker-chosen expression into post-sanitization shadow root content; the resulting script execution and any confidentiality or integrity consequence depend on the downstream engine's evaluation context.\n\n## Proof of Concept\n\n```text\nPreconditions:\n  - DOMPurify built from the affected source (dist/purify.js or an ESM/CJS bundle).\n  - A browser (or DOM implementation) with shadow DOM support.\n  - Application constructs a DOM node with an attached shadow root before sanitizing,\n    and later evaluates the shadow root's text content as a template.\n```\n\nBuild a host element whose shadow root holds a template expression split across text nodes separated by disallowed elements, then sanitize in place with `SAFE_FOR_TEMPLATES`:\n\n```javascript\nconst host = document.createElement('div');\nconst root = host.attachShadow({ mode: 'open' });\n\n// Split \"${alert(document.domain)}\" so no single fragment matches a regex.\n// \u003cobject\u003e is not in the default ALLOWED_TAGS and is removed during sanitization,\n// leaving the surrounding text-node siblings adjacent.\nroot.appendChild(document.createTextNode('$'));\nroot.appendChild(document.createElement('object'));\nroot.appendChild(document.createTextNode('{alert(document.domain)}'));\n\nDOMPurify.sanitize(host, { IN_PLACE: true, SAFE_FOR_TEMPLATES: true });\n\n// After the disallowed element is removed, the fragments are adjacent and survive.\nhost.shadowRoot.normalize();\nconsole.log(host.shadowRoot.textContent);\n```\n\n```text\n${alert(document.domain)}\n```\n\nA downstream template evaluator reading `shadowRoot.textContent` (for example `new Function('return `' + content + '`')()` or any `${...}`/`{{...}}` engine) then evaluates the fully formed expression.\n\n## Attack Chain\n\n1. **Exposure:** The application calls `DOMPurify.sanitize(node, cfg)` (`src/purify.ts:2854`) with `SAFE_FOR_TEMPLATES: true` and `IN_PLACE: true` (or a shadow-aware `RETURN_DOM`), passing a DOM node that already carries an attached shadow root.\n2. **Control:** The attacker controls the shadow root's text nodes and the disallowed separator elements between them; each fragment (`$`, `{alert(document.domain)}`) is a valid, individually benign text node.\n3. **Path:** `_sanitizeAttachedShadowRoots` (`src/purify.ts:2977`) feeds the shadow root into `_sanitizeShadowDOM` (`src/purify.ts:2710`), which strips expressions per text node (`src/purify.ts:2246`) and removes the disallowed separator elements, leaving the fragments adjacent.\n4. **Guard:** The post-walk safety net `_scrubTemplateExpressions` (`src/purify.ts:3131-3132`) is the only pass that would catch the merged expression, but it never recurses into shadow roots (`src/purify.ts:1717-1751` recurses into `\u003ctemplate\u003e.content` only).\n5. **Primitive:** The adjacent fragments serialize as a single concatenated string on `shadowRoot.textContent` / `shadowRoot.innerHTML`, reconstituting the complete expression.\n6. **Result:** A downstream template engine evaluates the attacker-chosen expression, achieving script execution (or template injection) in the engine's context.\n\n## Bypass Evidence\n\nThe relevant protection is `SAFE_FOR_TEMPLATES`, specifically the post-walk pass that defends against expressions that only form after adjacent text nodes merge. That defense was previously extended to `\u003ctemplate\u003e.content` under CVE-2026-65900 (GHSA-gvmj-g25r-r7wr) by adding `querySelectorAll('template')` recursion at `src/purify.ts:1743-1750`. The strongest challenge is whether any code path performs the equivalent merge-and-rescrub inside shadow roots. Enumerating every call site of `_scrubTemplateExpressions` (`src/purify.ts:1717`, `1747`, `3132`, `3141`) shows none receive a shadow root, and `_sanitizeShadowDOM` (`src/purify.ts:2710`) never calls `_scrubTemplateExpressions` or `normalize()`. The per-node strip cannot compensate: `MUSTACHE_EXPR` (`src/regexp.ts:3`) requires `{{` or `}}`, `TMPLIT_EXPR` (`src/regexp.ts:5`) requires `${`, and `ERB_EXPR` (`src/regexp.ts:4`) requires `\u003c%` or `%\u003e`, none of which appear in a single-character fragment. The CVE-2026-65900 regression tests exercise `\u003ctemplate\u003e.content` only; no test covers shadow root content under `SAFE_FOR_TEMPLATES`. The gap is therefore an unfixed case on a distinct remediation boundary (shadow roots) rather than a bypass of the delivered template-content fix.\n\n## Affected Versions\n\n- **Ecosystem:** `npm`\n- **Package:** `dompurify`\n- **Confirmed affected range:** `\u003e= 3.4.4, \u003c= 3.4.16`\n- **Latest release checked:** `3.4.16` ([npm registry](https://www.npmjs.com/package/dompurify/v/3.4.16))\n- **Fix status:** not fixed\n\nThe lower bound 3.4.4 is the release that introduced both the attached-shadow-root sanitization pass and the `_scrubTemplateExpressions` safety net; releases 3.4.4 through 3.4.7 carry the safety net with no content-container recursion, and 3.4.8 onward add `\u003ctemplate\u003e.content` recursion but still omit shadow root recursion. No published release and no current development revision contains a shadow-root fix.\n\n## Suggested Fix\n\nEnforce the same post-walk normalize-and-rescrub invariant on attached shadow roots that already applies to `\u003ctemplate\u003e.content`. After `_sanitizeShadowDOM` finishes walking a shadow root, run `_scrubTemplateExpressions` over that shadow root so adjacent text nodes created by element removal are merged and re-stripped; alternatively, have `_scrubTemplateExpressions` discover and recurse into attached shadow roots as it does for template content. The fix must cover nested shadow roots and shadow roots inside `\u003ctemplate\u003e.content`, and it must handle all three expression dialects, since any disallowed element can serve as the separator that produces adjacent fragments.\n\n---\n\nReported by zx (GitHub: @manus-pi).","status":"published","published":"2026-10-22T16:25:31Z","modified":"2026-10-22T16:25:32Z","cvss":[{"version":"4.0","score":9.2,"vector":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:L/SC:N/SI:N/SA:N","level":"critical"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T14:41:34.690842Z"}],"nvd":[{"id":"CVE-2026-116804","description":"DOMPurify from 3.4.4 before 3.4.17 contains a SAFE_FOR_TEMPLATES bypass that lets attackers preserve template expressions in attached shadow roots when using RETURN_DOM, RETURN_DOM_FRAGMENT, or IN_PLACE modes. Attackers can split expressions across text nodes separated by disallowed elements, which merge after removal and are evaluated by downstream template engines for cross-site scripting.","status":"published","published":"2026-10-27T00:17:12.193Z","modified":"2026-11-02T19:17:58.353Z","cvss":[{"version":"4.0","score":5.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"medium","assessor":"secondary"},{"version":"3.1","score":6.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N","level":"medium","assessor":"secondary"}],"cwes":["CWE-79"],"updated_at":"2026-11-03T00:02:36.126212Z"}],"osv":[{"id":"CVE-2026-116804","title":"DOMPurify from 3.4.4 before 3.4.17 SAFE_FOR_TEMPLATES Bypass via Shadow Root Content","description":"DOMPurify from 3.4.4 before 3.4.17 contains a SAFE_FOR_TEMPLATES bypass that lets attackers preserve template expressions in attached shadow roots when using RETURN_DOM, RETURN_DOM_FRAGMENT, or IN_PLACE modes. Attackers can split expressions across text nodes separated by disallowed elements, which merge after removal and are evaluated by downstream template engines for cross-site scripting.","status":"published","published":"2026-10-26T23:05:35.85Z","modified":"2026-11-04T02:31:04.67231412Z","cvss":[{"version":"4.0","score":5.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N","level":"medium"}],"cwes":["CWE-79"],"updated_at":"2026-11-04T02:54:44.889498Z"},{"id":"DEBIAN-CVE-2026-116804","description":"DOMPurify from 3.4.4 before 3.4.17 contains a SAFE_FOR_TEMPLATES bypass that lets attackers preserve template expressions in attached shadow roots when using RETURN_DOM, RETURN_DOM_FRAGMENT, or IN_PLACE modes. Attackers can split expressions across text nodes separated by disallowed elements, which merge after removal and are evaluated by downstream template engines for cross-site scripting.","status":"published","published":"2026-10-27T00:17:12.193Z","modified":"2026-11-03T10:00:32.547677532Z","cvss":[{"version":"4.0","score":5.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"medium"}],"updated_at":"2026-11-03T10:27:58.933618Z"},{"id":"GHSA-cg2g-xh64-v4q7","title":"DOMPurify SAFE_FOR_TEMPLATES bypass: split template expressions survive in attached shadow root content on DOM output modes","description":"## Summary\n\nWhen DOMPurify is configured with `SAFE_FOR_TEMPLATES: true` together with a DOM-returning mode (`RETURN_DOM: true`, `RETURN_DOM_FRAGMENT: true`, or `IN_PLACE: true`), template expressions such as `{{...}}`, `${...}`, and `\u003c%...%\u003e` survive sanitization inside the text content of an attached shadow root. The post-walk safety net `_scrubTemplateExpressions` (`src/purify.ts:1717`) was extended to recurse into `\u003ctemplate\u003e.content`, but it never recurses into attached shadow roots. An attacker who can supply a DOM node carrying a shadow root (the `IN_PLACE` and shadow-aware `RETURN_DOM` surfaces) can split an expression across text nodes separated by disallowed elements; after those elements are removed the fragments become adjacent and serialize into a complete expression that a downstream template engine will evaluate.\n\n## Root Cause\n\n`SAFE_FOR_TEMPLATES` neutralizes template expressions through two mechanisms: a per-text-node strip during the main walk (`_stripTemplateExpressions`, applied in `_sanitizeElements` at `src/purify.ts:2246`), and a final post-walk pass (`_scrubTemplateExpressions`, `src/purify.ts:1717`) that normalizes adjacent text nodes and re-strips expressions that only form after merging. The per-node strip cannot catch an expression that is split into individual fragments, because each fragment fails the delimiter regexes. The post-walk pass is the only mechanism that would catch the merged form, but it is structurally unable to reach shadow root content.\n\n```text\n_scrubTemplateExpressions (src/purify.ts:1717-1751):\n  - node.normalize() at line 1718 does not merge text nodes inside shadow roots (DOM spec).\n  - NodeIterator at lines 1723-1731 does not descend into shadow trees (DOM spec).\n  - Explicit recursion at lines 1743-1750 enters \u003ctemplate\u003e.content only, via\n    querySelectorAll('template'); there is no equivalent recursion into attached\n    shadow roots.\nShadow roots are sanitized earlier by _sanitizeShadowDOM (src/purify.ts:2710), which\napplies the per-node strip but never performs the post-walk normalize-and-rescrub.\n```\n\nShadow root text nodes are therefore sanitized only per-node and never re-examined as a merged unit.\n\n## Impact\n\nAn attacker who controls DOM-node input containing an attached shadow root can inject template expressions that survive sanitization and are later evaluated by the application's template engine. In client-side contexts this yields cross-site scripting; in a server-side template context it can escalate to template injection. Exploitation requires non-default application configuration: the application must enable `SAFE_FOR_TEMPLATES` and a DOM-returning mode, pass a DOM node that already has an attached shadow root, and feed the sanitized shadow root content into a template evaluator. The shadow root does not have to be built programmatically with `attachShadow`: in engines that support declarative shadow DOM, attacker-supplied markup containing `\u003ctemplate shadowrootmode=\"open\"\u003e` parsed through `setHTMLUnsafe` or `Document.parseHTMLUnsafe` produces the same attached shadow root, so a plain HTML string reaches the gap once the application is configured this way. Demonstrated capability is injection of a complete, attacker-chosen expression into post-sanitization shadow root content; the resulting script execution and any confidentiality or integrity consequence depend on the downstream engine's evaluation context.\n\n## Proof of Concept\n\n```text\nPreconditions:\n  - DOMPurify built from the affected source (dist/purify.js or an ESM/CJS bundle).\n  - A browser (or DOM implementation) with shadow DOM support.\n  - Application constructs a DOM node with an attached shadow root before sanitizing,\n    and later evaluates the shadow root's text content as a template.\n```\n\nBuild a host element whose shadow root holds a template expression split across text nodes separated by disallowed elements, then sanitize in place with `SAFE_FOR_TEMPLATES`:\n\n```javascript\nconst host = document.createElement('div');\nconst root = host.attachShadow({ mode: 'open' });\n\n// Split \"${alert(document.domain)}\" so no single fragment matches a regex.\n// \u003cobject\u003e is not in the default ALLOWED_TAGS and is removed during sanitization,\n// leaving the surrounding text-node siblings adjacent.\nroot.appendChild(document.createTextNode('$'));\nroot.appendChild(document.createElement('object'));\nroot.appendChild(document.createTextNode('{alert(document.domain)}'));\n\nDOMPurify.sanitize(host, { IN_PLACE: true, SAFE_FOR_TEMPLATES: true });\n\n// After the disallowed element is removed, the fragments are adjacent and survive.\nhost.shadowRoot.normalize();\nconsole.log(host.shadowRoot.textContent);\n```\n\n```text\n${alert(document.domain)}\n```\n\nA downstream template evaluator reading `shadowRoot.textContent` (for example `new Function('return `' + content + '`')()` or any `${...}`/`{{...}}` engine) then evaluates the fully formed expression.\n\n## Attack Chain\n\n1. **Exposure:** The application calls `DOMPurify.sanitize(node, cfg)` (`src/purify.ts:2854`) with `SAFE_FOR_TEMPLATES: true` and `IN_PLACE: true` (or a shadow-aware `RETURN_DOM`), passing a DOM node that already carries an attached shadow root.\n2. **Control:** The attacker controls the shadow root's text nodes and the disallowed separator elements between them; each fragment (`$`, `{alert(document.domain)}`) is a valid, individually benign text node.\n3. **Path:** `_sanitizeAttachedShadowRoots` (`src/purify.ts:2977`) feeds the shadow root into `_sanitizeShadowDOM` (`src/purify.ts:2710`), which strips expressions per text node (`src/purify.ts:2246`) and removes the disallowed separator elements, leaving the fragments adjacent.\n4. **Guard:** The post-walk safety net `_scrubTemplateExpressions` (`src/purify.ts:3131-3132`) is the only pass that would catch the merged expression, but it never recurses into shadow roots (`src/purify.ts:1717-1751` recurses into `\u003ctemplate\u003e.content` only).\n5. **Primitive:** The adjacent fragments serialize as a single concatenated string on `shadowRoot.textContent` / `shadowRoot.innerHTML`, reconstituting the complete expression.\n6. **Result:** A downstream template engine evaluates the attacker-chosen expression, achieving script execution (or template injection) in the engine's context.\n\n## Bypass Evidence\n\nThe relevant protection is `SAFE_FOR_TEMPLATES`, specifically the post-walk pass that defends against expressions that only form after adjacent text nodes merge. That defense was previously extended to `\u003ctemplate\u003e.content` under CVE-2026-65900 (GHSA-gvmj-g25r-r7wr) by adding `querySelectorAll('template')` recursion at `src/purify.ts:1743-1750`. The strongest challenge is whether any code path performs the equivalent merge-and-rescrub inside shadow roots. Enumerating every call site of `_scrubTemplateExpressions` (`src/purify.ts:1717`, `1747`, `3132`, `3141`) shows none receive a shadow root, and `_sanitizeShadowDOM` (`src/purify.ts:2710`) never calls `_scrubTemplateExpressions` or `normalize()`. The per-node strip cannot compensate: `MUSTACHE_EXPR` (`src/regexp.ts:3`) requires `{{` or `}}`, `TMPLIT_EXPR` (`src/regexp.ts:5`) requires `${`, and `ERB_EXPR` (`src/regexp.ts:4`) requires `\u003c%` or `%\u003e`, none of which appear in a single-character fragment. The CVE-2026-65900 regression tests exercise `\u003ctemplate\u003e.content` only; no test covers shadow root content under `SAFE_FOR_TEMPLATES`. The gap is therefore an unfixed case on a distinct remediation boundary (shadow roots) rather than a bypass of the delivered template-content fix.\n\n## Affected Versions\n\n- **Ecosystem:** `npm`\n- **Package:** `dompurify`\n- **Confirmed affected range:** `\u003e= 3.4.4, \u003c= 3.4.16`\n- **Latest release checked:** `3.4.16` ([npm registry](https://www.npmjs.com/package/dompurify/v/3.4.16))\n- **Fix status:** not fixed\n\nThe lower bound 3.4.4 is the release that introduced both the attached-shadow-root sanitization pass and the `_scrubTemplateExpressions` safety net; releases 3.4.4 through 3.4.7 carry the safety net with no content-container recursion, and 3.4.8 onward add `\u003ctemplate\u003e.content` recursion but still omit shadow root recursion. No published release and no current development revision contains a shadow-root fix.\n\n## Suggested Fix\n\nEnforce the same post-walk normalize-and-rescrub invariant on attached shadow roots that already applies to `\u003ctemplate\u003e.content`. After `_sanitizeShadowDOM` finishes walking a shadow root, run `_scrubTemplateExpressions` over that shadow root so adjacent text nodes created by element removal are merged and re-stripped; alternatively, have `_scrubTemplateExpressions` discover and recurse into attached shadow roots as it does for template content. The fix must cover nested shadow roots and shadow roots inside `\u003ctemplate\u003e.content`, and it must handle all three expression dialects, since any disallowed element can serve as the separator that produces adjacent fragments.\n\n---\n\nReported by zx (GitHub: @manus-pi).","status":"published","published":"2026-10-22T16:25:31Z","modified":"2026-10-27T10:56:08.031469803Z","cvss":[{"version":"4.0","score":9.2,"vector":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:L/SC:N/SI:N/SA:N","level":"critical"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T15:46:44.927642Z"},{"id":"UBUNTU-CVE-2026-116804","description":"DOMPurify from 3.4.4 before 3.4.17 contains a SAFE_FOR_TEMPLATES bypass that lets attackers preserve template expressions in attached shadow roots when using RETURN_DOM, RETURN_DOM_FRAGMENT, or IN_PLACE modes. Attackers can split expressions across text nodes separated by disallowed elements, which merge after removal and are evaluated by downstream template engines for cross-site scripting.","status":"published","published":"2026-10-27T00:17:00Z","modified":"2026-10-28T20:17:46.299369444Z","cvss":[{"version":"3.1","score":6.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N","level":"medium"},{"version":"4.0","score":5.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N","level":"medium"}],"updated_at":"2026-11-02T16:56:00.081948Z"},{"id":"CLSA-2026-1793100794","title":"TuxCare security update for dompurify (3 CVEs)","description":"TuxCare rebuilt dompurify to address 3 CVEs. Fixed in 3.4.5-tuxcare.5.","status":"published","published":"2026-10-27T11:33:14Z","modified":"2026-10-27T13:30:09.760475844Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793100979","title":"TuxCare security update for dompurify (3 CVEs)","description":"TuxCare rebuilt dompurify to address 3 CVEs. Fixed in 3.4.8-tuxcare.7.","status":"published","published":"2026-10-27T11:36:19Z","modified":"2026-10-27T13:30:08.308226646Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793101079","title":"TuxCare security update for dompurify (3 CVEs)","description":"TuxCare rebuilt dompurify to address 3 CVEs. Fixed in 3.4.13-tuxcare.3.","status":"published","published":"2026-10-27T11:37:59Z","modified":"2026-10-27T13:30:10.473558019Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793101206","title":"TuxCare security update for dompurify (3 CVEs)","description":"TuxCare rebuilt dompurify to address 3 CVEs. Fixed in 3.4.11-tuxcare.5.","status":"published","published":"2026-10-27T11:40:06Z","modified":"2026-10-27T13:30:09.756569656Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793101291","title":"TuxCare security update for dompurify (3 CVEs)","description":"TuxCare rebuilt dompurify to address 3 CVEs. Fixed in 3.4.6-tuxcare.5.","status":"published","published":"2026-10-27T11:41:31Z","modified":"2026-10-27T13:30:08.315711744Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793101437","title":"TuxCare security update for dompurify (3 CVEs)","description":"TuxCare rebuilt dompurify to address 3 CVEs. Fixed in 3.4.7-tuxcare.5.","status":"published","published":"2026-10-27T11:43:57Z","modified":"2026-10-27T13:30:08.310514508Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793101539","title":"TuxCare security update for dompurify (3 CVEs)","description":"TuxCare rebuilt dompurify to address 3 CVEs. Fixed in 3.4.14-tuxcare.4.","status":"published","published":"2026-10-27T11:45:39Z","modified":"2026-10-27T13:30:13.028155973Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793101597","title":"TuxCare security update for dompurify (3 CVEs)","description":"TuxCare rebuilt dompurify to address 3 CVEs. Fixed in 3.4.9-tuxcare.5.","status":"published","published":"2026-10-27T11:46:37Z","modified":"2026-10-27T13:30:17.548231676Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793101938","title":"TuxCare security update for dompurify (3 CVEs)","description":"TuxCare rebuilt dompurify to address 3 CVEs. Fixed in 3.4.10-tuxcare.5.","status":"published","published":"2026-10-27T11:52:18Z","modified":"2026-10-27T13:30:17.544935458Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793102164","title":"TuxCare security update for dompurify (4 CVEs)","description":"TuxCare rebuilt dompurify to address 4 CVEs. Fixed in 3.4.12-tuxcare.3.","status":"published","published":"2026-10-27T11:56:04Z","modified":"2026-10-27T13:30:18.441793863Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793102424","title":"TuxCare security update for dompurify (3 CVEs)","description":"TuxCare rebuilt dompurify to address 3 CVEs. Fixed in 3.4.15-tuxcare.3.","status":"published","published":"2026-10-27T12:00:24Z","modified":"2026-10-27T13:30:11.874311351Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793120002","title":"TuxCare security update for dompurify (2 CVEs)","description":"TuxCare rebuilt dompurify to address 2 CVEs. Fixed in 3.4.16-tuxcare.1.","status":"published","published":"2026-10-27T16:53:22Z","modified":"2026-10-28T01:58:05.089382782Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793348733","title":"TuxCare security update for dompurify (1 CVE)","description":"TuxCare rebuilt dompurify to address 1 CVE. Fixed in 3.4.8-tuxcare.8.","status":"published","published":"2026-10-30T09:25:34Z","modified":"2026-10-30T13:30:12.234880302Z","updated_at":"2026-11-02T15:43:55.669514Z"},{"id":"CLSA-2026-1793348774","title":"TuxCare security update for dompurify (1 CVE)","description":"TuxCare rebuilt dompurify to address 1 CVE. Fixed in 3.4.9-tuxcare.6.","status":"published","published":"2026-10-30T09:26:15Z","modified":"2026-10-30T13:30:11.429848873Z","updated_at":"2026-11-02T15:43:55.669514Z"},{"id":"CLSA-2026-1793348834","title":"TuxCare security update for dompurify (1 CVE)","description":"TuxCare rebuilt dompurify to address 1 CVE. Fixed in 3.4.10-tuxcare.6.","status":"published","published":"2026-10-30T09:27:15Z","modified":"2026-10-30T13:30:11.636724454Z","updated_at":"2026-11-02T15:43:55.669514Z"},{"id":"CLSA-2026-1793348929","title":"TuxCare security update for dompurify (1 CVE)","description":"TuxCare rebuilt dompurify to address 1 CVE. Fixed in 3.4.5-tuxcare.6.","status":"published","published":"2026-10-30T09:28:50Z","modified":"2026-10-30T13:30:12.287815354Z","updated_at":"2026-11-02T15:43:55.669514Z"},{"id":"CLSA-2026-1793349051","title":"TuxCare security update for dompurify (1 CVE)","description":"TuxCare rebuilt dompurify to address 1 CVE. Fixed in 3.4.12-tuxcare.4.","status":"published","published":"2026-10-30T09:30:51Z","modified":"2026-10-30T13:30:12.294251063Z","updated_at":"2026-11-02T15:43:55.669514Z"},{"id":"CLSA-2026-1793349529","title":"TuxCare security update for dompurify (1 CVE)","description":"TuxCare rebuilt dompurify to address 1 CVE. Fixed in 3.4.14-tuxcare.5.","status":"published","published":"2026-10-30T09:38:50Z","modified":"2026-10-30T13:30:11.637122606Z","updated_at":"2026-11-02T15:43:55.669514Z"},{"id":"CLSA-2026-1793349839","title":"TuxCare security update for dompurify (1 CVE)","description":"TuxCare rebuilt dompurify to address 1 CVE. Fixed in 3.4.11-tuxcare.6.","status":"published","published":"2026-10-30T09:44:00Z","modified":"2026-10-30T13:30:12.296979571Z","updated_at":"2026-11-02T15:43:55.669514Z"},{"id":"CLSA-2026-1793350195","title":"TuxCare security update for dompurify (1 CVE)","description":"TuxCare rebuilt dompurify to address 1 CVE. Fixed in 3.4.15-tuxcare.4.","status":"published","published":"2026-10-30T09:49:56Z","modified":"2026-10-30T13:30:12.349488422Z","updated_at":"2026-11-02T15:43:55.669514Z"},{"id":"ROOT-APP-NPM-GHSA-cg2g-xh64-v4q7","title":"GHSA-cg2g-xh64-v4q7 in dompurify - Patched by Root","description":"Root has patched GHSA-cg2g-xh64-v4q7 in the dompurify package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-11-02T09:55:56Z","modified":"2026-11-02T10:15:05.658263197Z","updated_at":"2026-11-02T15:53:27.940619Z"}]}}
