Vulnerability GHSA-c3jg-qh8m-j3h2

High Risk
HIGH RISK
CVSS Score: 8.0
Score Range: 7.0–8.9
High severity vulnerabilities (CVSS 7.0–8.9). Serious vulnerabilities that should be prioritized soon after critical fixes.
3 hours ago
October 08, 2026 at 07:41 PM UTC
CairoSVG: Quadratic-time DoS parsing a crafted SVG <path>
0.1 - 2.9.0
0.1 - 2.9.0

Summary

CairoSVG: Quadratic-time DoS parsing a crafted SVG <path>

Details

Summary

Rendering an untrusted SVG whose <path d="..."> contains many segments is O(n²) CPU. A single <path> under 1 MiB burns tens of seconds. Two independent O(n²) sites in cairosvg/path.py:

  1. Tokenizer — the path-data parser consumes the d string with a while string: loop that repeatedly slices/re-scans the remaining string (each step is O(len remaining)), giving O(n²) over the whole attribute.
  2. draw_markers — marker handling drains node.vertices with while node.vertices: ... node.vertices.pop(0); list.pop(0) is O(n), so draining n vertices is O(n²).

Both are hit on a normal render path (svg2png/svg2pdf), attacker controls only the SVG document.

PoC (installed cairosvg 2.9.0)

import cairosvg
d = "M0 0 " + "L1 1 " * 100000
svg = f'<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"><path d="{d}"/></svg>'
cairosvg.svg2png(bytestring=svg.encode())   # ~4.4 s for a 488 KB doc
path segments SVG size time
50,000 244 KB 1.14 s
100,000 488 KB 4.36 s
200,000 ~960 KB ~18 s

Doubling segments ≈ 4× time ⇒ quadratic. Sub-MiB input ⇒ ~18 s CPU; any service rendering user-supplied SVG (thumbnails, avatars, PDF export) is a DoS target.

Reachability

Public API svg2png / svg2pdf / svg2ps on an untrusted SVG string.

Suggested fix

Tokenize with a single forward scan / index (or re.finditer) instead of re-slicing the remainder; drain vertices with an index or collections.deque.popleft instead of list.pop(0). Optionally cap path-segment count.

Impacted packages

Timeline

Published
3 hours ago
October 08, 2026 at 07:41 PM UTC
Fixed (2.9.1)
1 month ago
September 07, 2026 at 10:35 AM UTC
Last Modified
3 hours ago
October 08, 2026 at 08:00 PM UTC