GHSA-c3jg-qh8m-j3h2

Suggest an improvement
Source
https://github.com/advisories/GHSA-c3jg-qh8m-j3h2
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-c3jg-qh8m-j3h2/GHSA-c3jg-qh8m-j3h2.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-c3jg-qh8m-j3h2
Aliases
  • CVE-2026-107378
Published
2026-10-08T19:41:22Z
Modified
2026-10-08T20:00:05Z
Severity
  • 8.7 (High) CVSS_V4 - CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N CVSS Calculator
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.

Database specific
{
    "cwe_ids": [
        "CWE-407"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-10-08T19:41:22Z",
    "nvd_published_at": "2026-10-08T18:17:23Z",
    "severity": "HIGH"
}
References

Affected packages

PyPI / cairosvg

Package

Affected ranges

Type
ECOSYSTEM
Events
Introduced
0 Unknown introduced version / All previous versions are affected
Fixed
2.9.1

Affected versions

0.*
0.1
0.1.1
0.1.2
0.2
0.3
0.3.1
0.4
0.4.1
0.4.2
0.4.3
0.4.4
0.5
1.*
1.0
1.0.1
1.0.2
1.0.3
1.0.4
1.0.5
1.0.6
1.0.7
1.0.8
1.0.9
1.0.10
1.0.11
1.0.12
1.0.13
1.0.14
1.0.15
1.0.16
1.0.17
1.0.18
1.0.19
1.0.20
1.0.21
1.0.22
2.*
2.0.0rc1
2.0.0rc2
2.0.0rc3
2.0.0rc4
2.0.0rc5
2.0.0rc6
2.0.0
2.0.1
2.0.2
2.0.3
2.1.0
2.1.1
2.1.2
2.1.3
2.2.0
2.2.1
2.3.0
2.3.1
2.4.0
2.4.1
2.4.2
2.5.0
2.5.1
2.5.2
2.6.0
2.7.0
2.7.1
2.8.0
2.8.1
2.8.2
2.9.0

Database specific

last_known_affected_version_range
"<= 2.9.0"
source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-c3jg-qh8m-j3h2/GHSA-c3jg-qh8m-j3h2.json"