{"id":"CVE-2026-107378","aliases":["DEBIAN-CVE-2026-107378","EUVD-2026-95135","GHSA-c3jg-qh8m-j3h2","PYSEC-2026-4204","ROOT-APP-PYPI-CVE-2026-107378","SUSE-SU-2026:24596-1","SUSE-SU-2026:4949-1","UBUNTU-CVE-2026-107378","openSUSE-SU-2026:12111-1","openSUSE-SU-2026:22182-1"],"status":"published","title":"CairoSVG: Quadratic-time DoS parsing a crafted SVG \u003cpath\u003e","description":"CairoSVG is an SVG converter based on Cairo, a 2D graphics library. Prior to 2.9.1, rendering an attacker-controlled SVG with a path containing many segments can cause quadratic CPU consumption in cairosvg/path.py. The path tokenizer repeatedly slices and rescans the remaining path data, while draw_markers drains node.vertices with node.vertices.pop(0), causing repeated linear-time work. The svg2png, svg2pdf, and svg2ps APIs reach these operations during ordinary rendering, allowing a sub-megabyte SVG to consume substantial CPU and deny service to a rendering application. This issue is fixed in version 2.9.1.","severity":{"version":"4.0","score":8.7,"vector":"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","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-12","score":0.00383,"percentile":0.32816,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-407"],"published":"2026-10-08T17:59:09Z","modified":"2026-11-10T17:27:19Z","fixes":[{"ecosystem":"PyPI","package":"cairosvg","fixed_in":["2.9.1"],"sources":["ghsa","osv"]},{"ecosystem":"Debian:14","package":"cairosvg","fixed_in":["2.9.1-1"],"sources":["osv"]},{"ecosystem":"Root:PyPI","package":"cairosvg","fixed_in":["2.7.1+aikido.6","2.7.1+aikido.7"],"sources":["osv"]},{"ecosystem":"SUSE:Linux Enterprise Server 16.0","package":"python-CairoSVG","fixed_in":["2.7.1-160000.4.1"],"sources":["osv"]},{"ecosystem":"SUSE:Linux Enterprise Server for SAP applications 16.0","package":"python-CairoSVG","fixed_in":["2.7.1-160000.4.1"],"sources":["osv"]},{"ecosystem":"SUSE:Linux Enterprise Module for Python 3 15 SP7","package":"python-CairoSVG","fixed_in":["2.7.1-150400.9.9.1"],"sources":["osv"]},{"ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP4-ESPOS","package":"python-CairoSVG","fixed_in":["2.7.1-150400.9.9.1"],"sources":["osv"]},{"ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP4-LTSS","package":"python-CairoSVG","fixed_in":["2.7.1-150400.9.9.1"],"sources":["osv"]},{"ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP5-ESPOS","package":"python-CairoSVG","fixed_in":["2.7.1-150400.9.9.1"],"sources":["osv"]},{"ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP5-LTSS","package":"python-CairoSVG","fixed_in":["2.7.1-150400.9.9.1"],"sources":["osv"]},{"ecosystem":"SUSE:Linux Enterprise Server 15 SP4-LTSS","package":"python-CairoSVG","fixed_in":["2.7.1-150400.9.9.1"],"sources":["osv"]},{"ecosystem":"SUSE:Linux Enterprise Server 15 SP5-LTSS","package":"python-CairoSVG","fixed_in":["2.7.1-150400.9.9.1"],"sources":["osv"]},{"ecosystem":"SUSE:Linux Enterprise Server 15 SP6-LTSS","package":"python-CairoSVG","fixed_in":["2.7.1-150400.9.9.1"],"sources":["osv"]},{"ecosystem":"SUSE:Linux Enterprise Server for SAP Applications 15 SP4","package":"python-CairoSVG","fixed_in":["2.7.1-150400.9.9.1"],"sources":["osv"]},{"ecosystem":"SUSE:Linux Enterprise Server for SAP Applications 15 SP5","package":"python-CairoSVG","fixed_in":["2.7.1-150400.9.9.1"],"sources":["osv"]},{"ecosystem":"SUSE:Linux Enterprise Server for SAP Applications 15 SP6","package":"python-CairoSVG","fixed_in":["2.7.1-150400.9.9.1"],"sources":["osv"]},{"ecosystem":"openSUSE:Tumbleweed","package":"python-CairoSVG","fixed_in":["2.9.1-1.1"],"sources":["osv"]},{"ecosystem":"openSUSE:Leap 16.0","package":"python-CairoSVG","fixed_in":["2.7.1-160000.4.1"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"cairosvg","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"2.9.0"},{"fixed":"2.9.1"}]}]},{"source":"osv","ecosystem":"Debian:12","package":"cairosvg","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.5.2-1.1","2.5.2-1.1+deb12u1","2.7.0-1","2.7.1-1","2.7.1-2","2.8.2-1","2.9.0-1","2.9.0-2","2.9.1-1","2.9.1-2"]},{"source":"osv","ecosystem":"Debian:13","package":"cairosvg","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.7.1-2","2.8.2-1","2.9.0-1","2.9.0-2","2.9.1-1","2.9.1-2"]},{"source":"osv","ecosystem":"Debian:14","package":"cairosvg","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.9.1-1"}]}],"versions":["2.7.1-2","2.8.2-1","2.9.0-1","2.9.0-2"]},{"source":"osv","ecosystem":"PyPI","package":"cairosvg","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.9.1"}]}],"versions":["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.0","1.0.1","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.2","1.0.20","1.0.21","1.0.22","1.0.3","1.0.4","1.0.5","1.0.6","1.0.7","1.0.8","1.0.9","2.0.0","2.0.0rc1","2.0.0rc2","2.0.0rc3","2.0.0rc4","2.0.0rc5","2.0.0rc6","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"]},{"source":"osv","ecosystem":"PyPI","package":"cairosvg","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.9.1"}]}],"versions":["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.0","1.0.1","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.2","1.0.20","1.0.21","1.0.22","1.0.3","1.0.4","1.0.5","1.0.6","1.0.7","1.0.8","1.0.9","2.0.0","2.0.0rc1","2.0.0rc2","2.0.0rc3","2.0.0rc4","2.0.0rc5","2.0.0rc6","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"]},{"source":"osv","ecosystem":"Root:PyPI","package":"cairosvg","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.1+aikido.6"},{"fixed":"2.7.1+aikido.7"}]}]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server 16.0","package":"python-CairoSVG","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.1-160000.4.1"}]}]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP applications 16.0","package":"python-CairoSVG","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.1-160000.4.1"}]}]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Module for Python 3 15 SP7","package":"python-CairoSVG","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.1-150400.9.9.1"}]}]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP4-ESPOS","package":"python-CairoSVG","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.1-150400.9.9.1"}]}]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP4-LTSS","package":"python-CairoSVG","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.1-150400.9.9.1"}]}]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP5-ESPOS","package":"python-CairoSVG","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.1-150400.9.9.1"}]}]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP5-LTSS","package":"python-CairoSVG","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.1-150400.9.9.1"}]}]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server 15 SP4-LTSS","package":"python-CairoSVG","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.1-150400.9.9.1"}]}]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server 15 SP5-LTSS","package":"python-CairoSVG","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.1-150400.9.9.1"}]}]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server 15 SP6-LTSS","package":"python-CairoSVG","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.1-150400.9.9.1"}]}]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP Applications 15 SP4","package":"python-CairoSVG","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.1-150400.9.9.1"}]}]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP Applications 15 SP5","package":"python-CairoSVG","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.1-150400.9.9.1"}]}]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP Applications 15 SP6","package":"python-CairoSVG","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.1-150400.9.9.1"}]}]},{"source":"osv","ecosystem":"Ubuntu:16.04:LTS","package":"cairosvg","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.0.16-1","1.0.17-1","1.0.19-1"]},{"source":"osv","ecosystem":"Ubuntu:18.04:LTS","package":"cairosvg","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.0.20-1"]},{"source":"osv","ecosystem":"Ubuntu:20.04:LTS","package":"cairosvg","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.4.0-2","2.4.2-1"]},{"source":"osv","ecosystem":"Ubuntu:22.04:LTS","package":"cairosvg","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.5.0-1.1","2.5.2-1"]},{"source":"osv","ecosystem":"Ubuntu:24.04:LTS","package":"cairosvg","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.7.1-1"]},{"source":"osv","ecosystem":"openSUSE:Tumbleweed","package":"python-CairoSVG","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.9.1-1.1"}]}]},{"source":"osv","ecosystem":"openSUSE:Leap 16.0","package":"python-CairoSVG","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.1-160000.4.1"}]}]}],"products":[{"vendor":"kozea","product":"cairosvg"}],"references":[{"url":"https://github.com/Kozea/CairoSVG/security/advisories/GHSA-c3jg-qh8m-j3h2","tags":["x_refsource_CONFIRM","exploit","advisory","web","report"]},{"url":"https://github.com/Kozea/CairoSVG/commit/9d63f049f9988d0ddda3eb94564ac3a50a286523","tags":["x_refsource_MISC","fix","web","report"]},{"url":"https://github.com/Kozea/CairoSVG/commit/a4d585eb374724b79676e9cceaa9e9a1a4358565","tags":["x_refsource_MISC","fix","web","report"]},{"url":"https://github.com/Kozea/CairoSVG/releases/tag/2.9.1","tags":["x_refsource_MISC","web","report"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-107378","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-c3jg-qh8m-j3h2","tags":["advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/107xxx/CVE-2026-107378.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-107378","tags":["advisory"]},{"url":"https://github.com/Kozea/CairoSVG","tags":["package"]},{"url":"https://pypi.org/project/cairosvg","tags":["package"]},{"url":"https://www.suse.com/support/update/announcement/2026/suse-su-202624596-1/","tags":["advisory"]},{"url":"https://bugzilla.suse.com/1284832","tags":["report"]},{"url":"https://www.suse.com/security/cve/CVE-2026-107378","tags":["web"]},{"url":"https://www.suse.com/support/update/announcement/2026/suse-su-20264949-1/","tags":["advisory"]},{"url":"https://ubuntu.com/security/CVE-2026-107378","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-107378","tags":["report"]},{"url":"","tags":["advisory"]}],"sources":{"cve":[{"id":"CVE-2026-107378","title":"CairoSVG: Quadratic-time DoS parsing a crafted SVG \u003cpath\u003e","description":"CairoSVG is an SVG converter based on Cairo, a 2D graphics library. Prior to 2.9.1, rendering an attacker-controlled SVG with a path containing many segments can cause quadratic CPU consumption in cairosvg/path.py. The path tokenizer repeatedly slices and rescans the remaining path data, while draw_markers drains node.vertices with node.vertices.pop(0), causing repeated linear-time work. The svg2png, svg2pdf, and svg2ps APIs reach these operations during ordinary rendering, allowing a sub-megabyte SVG to consume substantial CPU and deny service to a rendering application. This issue is fixed in version 2.9.1.","status":"published","published":"2026-10-08T17:59:09.505Z","modified":"2026-10-08T18:31:17.147Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high","assessor":"cna"}],"cwes":["CWE-407"],"updated_at":"2026-11-02T13:45:14.072357Z"}],"euvd":[{"id":"EUVD-2026-95135","description":"CairoSVG is an SVG converter based on Cairo, a 2D graphics library. Prior to 2.9.1, rendering an attacker-controlled SVG with a path containing many segments can cause quadratic CPU consumption in cairosvg/path.py. The path tokenizer repeatedly slices and rescans the remaining path data, while draw_markers drains node.vertices with node.vertices.pop(0), causing repeated linear-time work. The svg2png, svg2pdf, and svg2ps APIs reach these operations during ordinary rendering, allowing a sub-megabyte SVG to consume substantial CPU and deny service to a rendering application. This issue is fixed in version 2.9.1.","status":"published","published":"2026-10-08T17:59:09Z","modified":"2026-10-08T18:31:17Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high"}],"updated_at":"2026-11-02T17:27:27.72962Z"}],"ghsa":[{"id":"GHSA-c3jg-qh8m-j3h2","title":"CairoSVG: Quadratic-time DoS parsing a crafted SVG \u003cpath\u003e","description":"## Summary\n\nRendering an untrusted SVG whose `\u003cpath d=\"...\"\u003e` contains many segments is O(n²) CPU. A single `\u003cpath\u003e` under 1 MiB burns tens of seconds. Two independent O(n²) sites in `cairosvg/path.py`:\n\n1. **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.\n2. **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²).\n\nBoth are hit on a normal render path (`svg2png`/`svg2pdf`), attacker controls only the SVG document.\n\n## PoC (installed cairosvg 2.9.0)\n\n```python\nimport cairosvg\nd = \"M0 0 \" + \"L1 1 \" * 100000\nsvg = f'\u003csvg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\"\u003e\u003cpath d=\"{d}\"/\u003e\u003c/svg\u003e'\ncairosvg.svg2png(bytestring=svg.encode())   # ~4.4 s for a 488 KB doc\n```\n\n| path segments | SVG size | time |\n|---|---|---|\n| 50,000 | 244 KB | 1.14 s |\n| 100,000 | 488 KB | 4.36 s |\n| 200,000 | ~960 KB | ~18 s |\n\nDoubling segments ≈ 4× time ⇒ quadratic. Sub-MiB input ⇒ ~18 s CPU; any service rendering user-supplied SVG (thumbnails, avatars, PDF export) is a DoS target.\n\n## Reachability\n\nPublic API `svg2png` / `svg2pdf` / `svg2ps` on an untrusted SVG string.\n\n## Suggested fix\n\nTokenize 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.","status":"published","published":"2026-10-08T19:41:22Z","modified":"2026-10-08T19:41:24Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high"}],"cwes":["CWE-407"],"updated_at":"2026-11-02T14:41:30.097746Z"}],"nvd":[{"id":"CVE-2026-107378","description":"CairoSVG is an SVG converter based on Cairo, a 2D graphics library. Prior to 2.9.1, rendering an attacker-controlled SVG with a path containing many segments can cause quadratic CPU consumption in cairosvg/path.py. The path tokenizer repeatedly slices and rescans the remaining path data, while draw_markers drains node.vertices with node.vertices.pop(0), causing repeated linear-time work. The svg2png, svg2pdf, and svg2ps APIs reach these operations during ordinary rendering, allowing a sub-megabyte SVG to consume substantial CPU and deny service to a rendering application. This issue is fixed in version 2.9.1.","status":"published","published":"2026-10-08T18:17:23.417Z","modified":"2026-10-08T21:33:42.423Z","cvss":[{"version":"4.0","score":8.7,"vector":"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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"high","assessor":"secondary"}],"cwes":["CWE-407"],"updated_at":"2026-11-02T14:12:55.142936Z"}],"osv":[{"id":"CVE-2026-107378","title":"CairoSVG: Quadratic-time DoS parsing a crafted SVG \u003cpath\u003e","description":"CairoSVG is an SVG converter based on Cairo, a 2D graphics library. Prior to 2.9.1, rendering an attacker-controlled SVG with a path containing many segments can cause quadratic CPU consumption in cairosvg/path.py. The path tokenizer repeatedly slices and rescans the remaining path data, while draw_markers drains node.vertices with node.vertices.pop(0), causing repeated linear-time work. The svg2png, svg2pdf, and svg2ps APIs reach these operations during ordinary rendering, allowing a sub-megabyte SVG to consume substantial CPU and deny service to a rendering application. This issue is fixed in version 2.9.1.","status":"published","published":"2026-10-08T17:59:09.505Z","modified":"2026-11-10T17:27:19.215434198Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high"}],"cwes":["CWE-407"],"updated_at":"2026-11-10T17:34:47.901646Z"},{"id":"DEBIAN-CVE-2026-107378","description":"CairoSVG is an SVG converter based on Cairo, a 2D graphics library. Prior to 2.9.1, rendering an attacker-controlled SVG with a path containing many segments can cause quadratic CPU consumption in cairosvg/path.py. The path tokenizer repeatedly slices and rescans the remaining path data, while draw_markers drains node.vertices with node.vertices.pop(0), causing repeated linear-time work. The svg2png, svg2pdf, and svg2ps APIs reach these operations during ordinary rendering, allowing a sub-megabyte SVG to consume substantial CPU and deny service to a rendering application. This issue is fixed in version 2.9.1.","status":"published","published":"2026-10-08T18:17:23.417Z","modified":"2026-11-03T23:00:05.923430957Z","cvss":[{"version":"4.0","score":8.7,"vector":"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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"high"}],"updated_at":"2026-11-03T23:33:35.474213Z"},{"id":"GHSA-c3jg-qh8m-j3h2","title":"CairoSVG: Quadratic-time DoS parsing a crafted SVG \u003cpath\u003e","description":"## Summary\n\nRendering an untrusted SVG whose `\u003cpath d=\"...\"\u003e` contains many segments is O(n²) CPU. A single `\u003cpath\u003e` under 1 MiB burns tens of seconds. Two independent O(n²) sites in `cairosvg/path.py`:\n\n1. **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.\n2. **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²).\n\nBoth are hit on a normal render path (`svg2png`/`svg2pdf`), attacker controls only the SVG document.\n\n## PoC (installed cairosvg 2.9.0)\n\n```python\nimport cairosvg\nd = \"M0 0 \" + \"L1 1 \" * 100000\nsvg = f'\u003csvg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\"\u003e\u003cpath d=\"{d}\"/\u003e\u003c/svg\u003e'\ncairosvg.svg2png(bytestring=svg.encode())   # ~4.4 s for a 488 KB doc\n```\n\n| path segments | SVG size | time |\n|---|---|---|\n| 50,000 | 244 KB | 1.14 s |\n| 100,000 | 488 KB | 4.36 s |\n| 200,000 | ~960 KB | ~18 s |\n\nDoubling segments ≈ 4× time ⇒ quadratic. Sub-MiB input ⇒ ~18 s CPU; any service rendering user-supplied SVG (thumbnails, avatars, PDF export) is a DoS target.\n\n## Reachability\n\nPublic API `svg2png` / `svg2pdf` / `svg2ps` on an untrusted SVG string.\n\n## Suggested fix\n\nTokenize 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.","status":"published","published":"2026-10-08T19:41:22Z","modified":"2026-10-15T14:56:21.119947482Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high"}],"cwes":["CWE-407"],"updated_at":"2026-11-02T15:46:44.571161Z"},{"id":"PYSEC-2026-4204","title":"CairoSVG: Quadratic-time DoS parsing a crafted SVG \u003cpath\u003e","description":"## Summary\n\nRendering an untrusted SVG whose `\u003cpath d=\"...\"\u003e` contains many segments is O(n²) CPU. A single `\u003cpath\u003e` under 1 MiB burns tens of seconds. Two independent O(n²) sites in `cairosvg/path.py`:\n\n1. **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.\n2. **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²).\n\nBoth are hit on a normal render path (`svg2png`/`svg2pdf`), attacker controls only the SVG document.\n\n## PoC (installed cairosvg 2.9.0)\n\n```python\nimport cairosvg\nd = \"M0 0 \" + \"L1 1 \" * 100000\nsvg = f'\u003csvg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\"\u003e\u003cpath d=\"{d}\"/\u003e\u003c/svg\u003e'\ncairosvg.svg2png(bytestring=svg.encode())   # ~4.4 s for a 488 KB doc\n```\n\n| path segments | SVG size | time |\n|---|---|---|\n| 50,000 | 244 KB | 1.14 s |\n| 100,000 | 488 KB | 4.36 s |\n| 200,000 | ~960 KB | ~18 s |\n\nDoubling segments ≈ 4× time ⇒ quadratic. Sub-MiB input ⇒ ~18 s CPU; any service rendering user-supplied SVG (thumbnails, avatars, PDF export) is a DoS target.\n\n## Reachability\n\nPublic API `svg2png` / `svg2pdf` / `svg2ps` on an untrusted SVG string.\n\n## Suggested fix\n\nTokenize 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.","status":"published","published":"2026-10-15T10:22:52.774841Z","modified":"2026-10-15T14:45:05.910064482Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high"}],"updated_at":"2026-11-02T15:52:57.671918Z"},{"id":"UBUNTU-CVE-2026-107378","description":"CairoSVG is an SVG converter based on Cairo, a 2D graphics library. Prior to 2.9.1, rendering an attacker-controlled SVG with a path containing many segments can cause quadratic CPU consumption in cairosvg/path.py. The path tokenizer repeatedly slices and rescans the remaining path data, while draw_markers drains node.vertices with node.vertices.pop(0), causing repeated linear-time work. The svg2png, svg2pdf, and svg2ps APIs reach these operations during ordinary rendering, allowing a sub-megabyte SVG to consume substantial CPU and deny service to a rendering application. This issue is fixed in version 2.9.1.","status":"published","published":"2026-10-08T18:17:00Z","modified":"2026-10-17T12:58:01.405773236Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high"}],"updated_at":"2026-11-02T16:55:59.130573Z"},{"id":"openSUSE-SU-2026:12111-1","title":"python313-CairoSVG-2.9.1-1.1 on GA media","description":"These are all security issues fixed in the python313-CairoSVG-2.9.1-1.1 package on the GA media of openSUSE Tumbleweed.","status":"published","published":"2026-10-12T00:00:00Z","modified":"2026-10-13T10:30:06.861362239Z","updated_at":"2026-11-02T16:58:40.245664Z"},{"id":"openSUSE-SU-2026:22182-1","title":"Security update for python-CairoSVG","description":"This update for python-CairoSVG fixes the following issue:\n\n- CVE-2026-107378: rendering an attacker-controlled SVG with a path containing many segments can lead to quadratic CPU\n  consumption (bsc#1284832).\n","status":"published","published":"2026-10-29T14:38:59Z","modified":"2026-10-31T18:00:09.294927619Z","updated_at":"2026-11-02T16:58:42.426393Z"},{"id":"ROOT-APP-PYPI-CVE-2026-107378","title":"CVE-2026-107378 in cairosvg - Patched by Root","description":"Root has patched CVE-2026-107378 in the cairosvg package for Root:PyPI. Multiple fixed versions available.","status":"published","published":"2026-10-20T13:53:49Z","modified":"2026-10-20T14:15:03.173090331Z","updated_at":"2026-11-02T15:53:27.940619Z"},{"id":"SUSE-SU-2026:24596-1","title":"Security update for python-CairoSVG","description":"This update for python-CairoSVG fixes the following issue:\n\n- CVE-2026-107378: rendering an attacker-controlled SVG with a path containing many segments can lead to quadratic CPU\n  consumption (bsc#1284832).\n","status":"published","published":"2026-10-29T14:40:40Z","modified":"2026-11-10T17:23:20.218716281Z","updated_at":"2026-11-10T17:35:04.393608Z"},{"id":"SUSE-SU-2026:4949-1","title":"Security update for python-CairoSVG","description":"This update for python-CairoSVG fixes the following issue:\n\n- CVE-2026-107378: rendering an attacker-controlled SVG with a path containing many segments can lead to quadratic CPU\n  consumption (bsc#1284832).\n","status":"published","published":"2026-10-30T09:58:02Z","modified":"2026-11-02T17:23:10.116707836Z","updated_at":"2026-11-02T18:00:32.560004Z"}]}}
