{"schema":"threatline.record/2","record":{"id":"CVE-2026-107378","aliases":["GHSA-c3jg-qh8m-j3h2","PYSEC-2026-4204"],"summary":"CairoSVG: Quadratic-time DoS parsing a crafted SVG <path>","details":"## Summary\n\nRendering 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`:\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'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\"><path d=\"{d}\"/></svg>'\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.","categories":["Libraries & packages"],"product":"cairosvg","vendor":"Kozea","ecosystem":"pip","affected_ranges":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-c3jg-qh8m-j3h2","source_modified_at":"2026-10-08T19:41:24Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"pip","name":"cairosvg"},"range":"<= 2.9.0"},{"source":"CVE List","source_url":"https://www.cve.org/CVERecord?id=CVE-2026-107378","source_modified_at":"2026-10-08T18:31:17.147Z","fetched_at":"2026-10-23T18:45:31.882637Z","product":"CairoSVG","vendor":"Kozea","versions":[{"version":"< 2.9.1","status":"affected"}],"defaultStatus":null},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-c3jg-qh8m-j3h2","source_modified_at":"2026-10-15T14:56:21.119947482Z","fetched_at":"2026-10-23T18:45:31.882637Z","package":{"name":"cairosvg","ecosystem":"PyPI","purl":"pkg:pypi/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"]}],"fixed_versions":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-c3jg-qh8m-j3h2","source_modified_at":"2026-10-08T19:41:24Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"pip","name":"cairosvg"},"version":"2.9.1"},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-c3jg-qh8m-j3h2","source_modified_at":"2026-10-15T14:56:21.119947482Z","fetched_at":"2026-10-23T18:45:31.882637Z","package":{"name":"cairosvg","ecosystem":"PyPI","purl":"pkg:pypi/cairosvg"},"version":"2.9.1"}],"cvss":8.7,"severity":"High","kev":{"listed":false},"epss":{"probability":0.00383,"percentile":0.31161,"score_date":"2026-10-23"},"published_at":"2026-10-08T17:59:09.505Z","modified_at":"2026-10-15T14:56:21.119947482Z","provenance":[{"source":"GitHub Advisory Database","url":"https://github.com/advisories/GHSA-c3jg-qh8m-j3h2","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-08T19:41:24Z"},{"source":"CVE List","url":"https://www.cve.org/CVERecord?id=CVE-2026-107378","fetched_at":"2026-10-23T18:45:31.882637Z","source_modified_at":"2026-10-08T18:31:17.147Z"},{"source":"OSV","url":"https://osv.dev/vulnerability/GHSA-c3jg-qh8m-j3h2","fetched_at":"2026-10-23T18:45:31.882637Z","source_modified_at":"2026-10-15T14:56:21.119947482Z"},{"source":"EPSS","url":"https://api.first.org/data/v1/epss?cve=CVE-2026-107378","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-23"}],"sources":["GitHub Advisory Database","CVE List","OSV","EPSS"],"references":[{"source":"CVE List","url":"https://github.com/Kozea/CairoSVG/security/advisories/GHSA-c3jg-qh8m-j3h2","tags":["exploit"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-107378","source":"GitHub Advisory Database"},{"source":"CVE List","url":"https://github.com/Kozea/CairoSVG/commit/9d63f049f9988d0ddda3eb94564ac3a50a286523","tags":["x_refsource_MISC"]},{"source":"CVE List","url":"https://github.com/Kozea/CairoSVG/commit/a4d585eb374724b79676e9cceaa9e9a1a4358565","tags":["x_refsource_MISC"]},{"source":"CVE List","url":"https://github.com/Kozea/CairoSVG/releases/tag/2.9.1","tags":["x_refsource_MISC"]},{"url":"https://github.com/advisories/GHSA-c3jg-qh8m-j3h2","source":"GitHub Advisory Database"}],"locations":[],"motoko_assessment":{"status":"requires_architecture_review","automatic_remediation":false},"cve_state":"PUBLISHED","ssvc":{"exploitation":"poc","automatable":"yes","technical_impact":"partial","assessed_at":"2026-10-08T18:31:09.975017Z"},"classification":{"method":"product-first software-layer rules","rules_version":"2.1","matched_on":"ecosystem","confidence":"heuristic","reviewed":false},"change_timestamp":"2026-10-15T14:56:21.119947482Z","content_hash":"97d542392c1066ea72717d9f25dce0d88cd7b7551956c53b626444ecd1e336bc"}}
