PackageTrack
Sign in Get early access

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 2026
2022 2023 2024 2025 2026
Release Pre-release

Releases

latest 15
  1. 1.0.14 10 Aug 2026
    Release notes

    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, so content:"/*" 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 [^)]*, so image-set(url(a.png) 1x, "https://evil" 2x) slipped past, as did the same candidate nested inside cross-fade(), and an external URL smuggled through a custom property and pulled back in with var(). 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 via content: 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.

    Open source →
  2. 1.0.13 07 Aug 2026
    Release notes

    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) or url(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\2a decodes to /*).

    image-set() never matched any pattern. It loads an external resource without ever writing url(), so none of the existing patterns applied — and unlike the comment payloads, browsers do fetch it. Both image-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.

    Open source →
  3. 1.0.12 06 Aug 2026
    Release notes

    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 or data: url() values. Inline style attributes were only matched against a pattern that required a quote after url(, 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) and url(https://host/x) without quotes — the reported vector
    • url("data:..."), which slipped through even when quoted
    • url (…) with whitespace before the parenthesis, URL(…) in uppercase, and a newline inside url()
    • CSS hex-escaped schemes and slashes, such as url(\\68 ttps://host/x) and url(\\2f\\2f host/x)
    • @import and expression() 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.

    Open source →
  4. 1.0.11 23 Apr 2026
    Release notes

    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
    Open source →
  5. 1.0.10 10 Apr 2026
    Release notes

    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 CSS url() references and @import rules 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 legacy expression(). CSS hex escapes like \75 rl(...) are decoded before matching so escape-based bypasses are caught. Fragment references such as url(#gradientId) are preserved so SVG <defs>, gradients, filters, and masks continue to work normally.
    Open source →
  6. 1.0.9 31 Mar 2026
    Release notes

    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.
    Open source →
  7. 1.0.8 15 Apr 2024
    Release notes

    Merge pull request #1 from DeepDiver1975/fix/removeattributens

    fix: disallow xlink:href

    Open source →
  8. 1.0.7 06 Nov 2023

    Nothing published for this version

  9. 1.0.6 30 Sep 2021

    Nothing published for this version

  10. 1.0.5 29 Sep 2021

    Nothing published for this version

  11. 1.0.4 24 Sep 2021

    Nothing published for this version

  12. 1.0.3 24 Sep 2021

    Nothing published for this version

  13. 1.0.2 23 Sep 2021

    Nothing published for this version

  14. 1.0.1 22 Sep 2021

    Nothing published for this version

  15. 1.0.0 22 Sep 2021

    Nothing published for this version

Every package, every release, already written down.

The archive is open and free. Watching your own project is what we are building next.

Browse the archive