GitHub Advisoryadvisory · Packagist

GHSA-m9xh-6747-9r6f svg-sanitizer: Mixed-case xlink:HrEf skips the `<use>` nesting-DoS check in Resolver::processReferences

MEDIUM Published 2026-10-08 Modified 2026-10-08 Official page ↗
Aliases
CVE-2026-107381
Ecosystem
Packagist
Packages
enshrined/svg-sanitize
Severity
Moderate
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H
Weaknesses
CWE-178, CWE-400
Reviewed
2026-10-08

Affected packages

• Packagist enshrined/svg-sanitize: < 1.0.0 → fixed in 1.0.0

Description

Summary `Resolver::processReferences()` collects `` elements with the XPath predicate `use[@href or @xlink:href]`, which is case sensitive. A `` element written as `xlink:HrEf` is therefore never added to the reference graph, so the nesting-DoS nullification never marks it for removal. `Sanitizer::cleanHrefAttributes()` then runs later in the same pass and rewrites `xlink:HrEf` back to the canonical `xlink:href`. The sanitizer hands back a fully live nesting bomb that it would have stripped completely had the input used canonical casing. This is the mirror image of CVE-2025-55166: that fix made href *value* checking case insensitive, but the `` reference graph still selects nodes case sensitively. Where it is `src/ElementReference/Resolver.php:97-118`, the case-sensitive node selection: ```php $useNodeName = $this->xPath->createNodeName('use'); foreach ($this->subjects as $subject) { $useElements = $this->xPath->query( $useNodeName . '[@href or @xlink:href]', $subject->getElement() ); ``` `src/Sanitizer.php:479-504`, the normalization that happens afterwards and makes the attribute live again: ```php // in case the attribute name is `HrEf`/`xlink:HrEf`, adjust it to `href`/`xlink:href` if (!in_array($attribute->nodeName, $this->allowedAttrs, true) && in_array(strtolower($attribute->nodeName), $this->allowedAttrs, true) ) { $element->removeAttribute($attribute->nodeName); $element->setAttribute(strtolower($attribute->nodeName), $attribute->value); } ``` Ordering is the whole bug. `Sanitizer::sanitize()` builds the resolver graph first and normalizes attribute casing second, so the graph is built against names the sanitizer is about to change. Impact Anyone who can submit an SVG to an application that sanitizes it with this library and then serves it. No privileges beyond being able to upload or paste an SVG. The output is the project's own `tests/data/useDosTest.svg` nesting structure, intact, with canonical `xlink:href` attributes, which is exactly the input the `useNestingLimit` machinery exists to defuse. Proof of concept Against a clean clone of tag `0.22.0`. The only change to the input is rewriting `xlink:href` to `xlink:HrEf` in the project's own DoS fixture. ```php removeRemoteReferences(true); $out = $s->sanitize($input); echo "[$label]\n"; echo " output elementReferenceResolver->collect()` rather than after, so the resolver only ever sees `href` and `xlink:href`. The second option also removes the general class of bug where the graph and the cleaner disagree about a node's identity.

Related

Alias · CVE (1)

Weakness · CWE (2)

  • CWE-178 Improper Handling of Case Sensitivity weakness
  • CWE-400 Uncontrolled Resource Consumption weakness

References