rhukster/dom-sanitizer
A simple but effective DOM/SVG/MathML Sanitizer for PHP 7.4+
1.0.14
3.1M downloads/mo
#1629 most downloaded on Packagist
rhukster/dom-sanitizer
What this package is like to depend on
Last release 13 days ago
10 Aug 2026
Release timing varies
gaps range from 9 days to 2.1 years
Some releases are documented
notes for 7 of 15 stable releases
Nothing withdrawn
no release was ever pulled
5 years old
15 releases · first in 2021
6 releases in the last 12 months
see the full history below
Release timeline
15 releases · Sep 2021 to Aug 2026Releases
latest 15-
1.0.1410 Aug 2026Release notes
Open source →Security
Two follow-up bypasses in the dangerous-CSS checks added in 1.0.13, both closed here (ref GHSA-ww22-4mqv-x5w3).
A
/*inside a string literal ate the rest of the stylesheet. Comment stripping used a plain regex, socontent:"/*"was read as the start of a comment; being unterminated, it swallowed everything after it and hid whatever dangerous tokens followed. That made 1.0.13 weaker than 1.0.12 for this shape. Comment stripping is now string-aware: a/*inside a"..."or'...'string is content, not a comment.image-set()matching could not cross a nested paren. The pattern used[^)]*, soimage-set(url(a.png) 1x, "https://evil" 2x)slipped past, as did the same candidate nested insidecross-fade(), and an external URL smuggled through a custom property and pulled back in withvar(). The regex is replaced by a single string- and paren-aware pass that flags an off-origin scheme in a quoted string whenever it is an argument, at any depth, to an image function or the value of a custom property.Relative
image-set()candidates,url(#fragment), and a URL shown only viacontent:are still left alone. Suite is green at 84 tests / 150 assertions.Anyone embedding untrusted SVG or HTML should update. Grav users should take the next Grav release, which bundles this version.
-
1.0.1307 Aug 2026Release notes
Open source →Security
The CSS checks introduced in 1.0.10 can be bypassed two ways, both closed in this release (GHSA-ww22-4mqv-x5w3).
Comments split the tokens the checks look for. The checks decoded CSS escapes but never removed comments, so a comment dropped inside a token hid it, e.g.
u/**/rl(https://host/x)orurl(htt/**/ps://host/x). CSS is now normalized before the dangerous-token checks run: comments are stripped, escapes are decoded, then comments are stripped a second time, because decoding can synthesize a comment that was not there on the first pass (\2f\2adecodes to/*).image-set()never matched any pattern. It loads an external resource without ever writingurl(), so none of the existing patterns applied — and unlike the comment payloads, browsers do fetch it. Bothimage-set()and-webkit-image-set()are now covered, while relative references still pass.Whitespace is deliberately left alone, since it is equally inert to browsers and collapsing it would risk rejecting legitimate multi-line CSS. Adds 9 regression cases; suite is green at 80 tests / 144 assertions.
Anyone embedding untrusted SVG or HTML should update. Grav users should take the next Grav release, which bundles this version.
-
1.0.1206 Aug 2026Release notes
Open source →Security
Inline
style=" attributes are now checked with the same CSS rules already applied to<style>` element text (GHSA-jfrr-ch68-f2w9). Reported by @Asadbeknur.Since 1.0.10,
<style>element text has been normalized for CSS escapes and checked for@import,expression()and external ordata:url()values. Inlinestyleattributes were only matched against a pattern that required a quote afterurl(, even though CSS makes those quotes optional. The same payload was therefore rejected inside a<style>block and accepted as an attribute.Closed in this release:
url(//host/x)andurl(https://host/x)without quotes — the reported vectorurl("data:..."), which slipped through even when quotedurl (…)with whitespace before the parenthesis,URL(…)in uppercase, and a newline insideurl()- CSS hex-escaped schemes and slashes, such as
url(\\68 ttps://host/x)andurl(\\2f\\2f host/x) @importandexpression()in an attribute value
Same-document references like
url(#gradient)and ordinary declarations are unaffected, and are covered by new preservation tests.Anyone embedding untrusted SVG or HTML should update. Grav users should take the next Grav release, which bundles this version.
-
1.0.1123 Apr 2026Release notes
Open source →Security
-
Harden loadDocument against XXE and entity-expansion attacks
-
Strip <!DOCTYPE> and <!ENTITY> declarations from sanitizer input before
parsing, then call loadXML/loadHTML with LIBXML_NONET so the parser cannot
make outbound filesystem or network requests for external entities/DTDs.
Also calls libxml_disable_entity_loader on PHP < 8 (no-op on PHP 8+,
where the default already declines external entities). -
Closes the dom-sanitizer half of GHSA-3446-6mgw-f79p (filed against Grav,
which uses this library as its SVG sanitizer). The companion fix in Grav
core is in VectorImageMedium's dimension reader. -
Two new XXE regression tests added to DomSanitizerTest:
- file:// SYSTEM entity payload — must not expand into /etc/passwd
- billion-laughs DOCTYPE — must not balloon memory
-
-
1.0.1010 Apr 2026Release notes
Open source →Security
- Fixed CSS injection via SVG/HTML
<style>text content (GHSA-93vf-569f-22cq) —DOMSanitizer::sanitize()allowed<style>elements in both SVG and HTML mode but never inspected their text content, letting CSSurl()references and@importrules pass through unfiltered. An attacker could exfiltrate the page URL to an external host, load arbitrary stylesheets, or use CSS attribute-selector tricks to leak form token values. The fix walks<style>text nodes and drops the element if it contains@import,url(...)with an external scheme (http:,https:,ftp:,//,data:), or legacyexpression(). CSS hex escapes like\75 rl(...)are decoded before matching so escape-based bypasses are caught. Fragment references such asurl(#gradientId)are preserved so SVG<defs>, gradients, filters, and masks continue to work normally.
- Fixed CSS injection via SVG/HTML
-
1.0.931 Mar 2026Release notes
Open source →Security & Bug Fixes
Security
- Fixed SVG sanitizer bypass via ASCII whitespace entities (#6) — Addresses a bypass of the
CVE-2026-33172 fix where character entities like (tab), (newline), and (CR) could be used to smuggle javascript: URIs
past the regex-based sanitization. The fix adds DOM-level URL scheme validation that operates on decoded attribute values, eliminating this
entire class of entity-encoding bypasses. - Added comprehensive XSS event handler tests for GHSA-gxwg-x2jg-q44j to improve test coverage of onload, onclick, onerror, onmouseover, and
other event handler stripping across SVG and HTML contexts. - Added SECURITY.md with instructions for private vulnerability reporting.
Bug Fixes
- Fixed SVG filter elements being incorrectly removed (#5) — SVG filter tags
(feGaussianBlur, feBlend, feColorMatrix, etc.) were defined in camelCase but compared against lowercased tag names, causing all filter
elements to be silently stripped during sanitization.
- Fixed SVG sanitizer bypass via ASCII whitespace entities (#6) — Addresses a bypass of the
-
1.0.815 Apr 2024Release notes
Open source →Merge pull request #1 from DeepDiver1975/fix/removeattributens
fix: disallow xlink:href
-
1.0.706 Nov 2023Nothing published for this version
-
1.0.630 Sep 2021Nothing published for this version
-
1.0.529 Sep 2021Nothing published for this version
-
1.0.424 Sep 2021Nothing published for this version
-
1.0.324 Sep 2021Nothing published for this version
-
1.0.223 Sep 2021Nothing published for this version
-
1.0.122 Sep 2021Nothing published for this version
-
1.0.022 Sep 2021Nothing published for this version