Skip to content
Heist/ feed
Back to feed
MediumFix available

fpdf2: Exponential SVG '' expansion causes CPU and memory exhaustion in 'FPDF.image()'

Type: advisorySources: OSV

### Summary fpdf2 expands SVG `` references by deep-copying the complete referenced graphics tree. A small SVG can use nested references to make the number of in-memory objects grow exponentially, causing excessive CPU and memory consumption during `FPDF.image()` processing. This was reproduced with an 895-byte SVG on fpdf2 2.8.7. Under a 128 MB process limit, the input kept the process busy for about 14 seconds before raising `MemoryError`. ### Details The issue is in fpdf2's own SVG reference handling. It does not rely on XML entities, external URLs, local files, or vulnerable behavior in another dependency. When fpdf2 resolves an SVG reference, [`SVGObject.build_xref()`](https://github.com/py-pdf/fpdf2/blob/a3307f96a0d165831029b3fb644aee5a7ca03328/fpdf/svg.py#L1584) passes the referenced object to `GraphicsContext.add_item()`: ```python pdf_group.add_item(self.cross_references[ref]) ``` [`GraphicsContext.add_item()`](https://github.com/py-pdf/fpdf2/blob/a3307f96a0d165831029b3fb644aee5a7ca03328/fpdf/drawing.py#L3618-L3633) uses `clone=True` by default and deep-copies the object: ```python def add_item(self, item, clone=True): if clone: item = deepcopy(item) self.path_items.append(item) ``` An attacker can define `g1` as eight references to `g0`, `g2` as eight references to `g1`, and so on. Each level adds only a small amount of XML, but fpdf2 copies the entire tree from the previous level eight times. The resulting work grows approximately as `8^n`. `ResourceAccessPolicy` d

Products
fpdf2
Affected versions
2.5.0, 2.5.1, 2.5.2, 2.5.3, 2.5.4, 2.5.5, 2.5.6, 2.5.7, 2.6.0, 2.6.1, 2.7.0, 2.7.1, 2.7.2, 2.7.3, 2.7.4, 2.7.5, 2.7.6, 2.7.7, 2.7.8, 2.7.9, 2.8.1, 2.8.2, 2.8.3, 2.8.4, 2.8.5, 2.8.6, 2.8.7
Fixed versions
2.8.8
CVEs
CVE-2026-114610
Confirmed fixed CVEs
Not specified
Updated in this feed
1 Nov 2026, 18:43 UTC · Revision 1

Source evidence

fpdf2: Exponential SVG '' expansion causes CPU and memory exhaustion in 'FPDF.image()'

core-osv · Original source

Published 27 Oct 2026, 14:43 UTC

### Summary fpdf2 expands SVG `` references by deep-copying the complete referenced graphics tree. A small SVG can use nested references to make the number of in-memory objects grow exponentially, causing excessive CPU and memory consumption during `FPDF.image()` processing. This was reproduced with an 895-byte SVG on fpdf2 2.8.7. Under a 128 MB process limit, the input kept the process busy for about 14 seconds before raising `MemoryError`. ### Details The issue is in fpdf2's own SVG reference handling. It does not rely on XML entities, external URLs, local files, or vulnerable behavior in another dependency. When fpdf2 resolves an SVG reference, [`SVGObject.build_xref()`](https://github.com/py-pdf/fpdf2/blob/a3307f96a0d165831029b3fb644aee5a7ca03328/fpdf/svg.py#L1584) passes the referenced object to `GraphicsContext.add_item()`: ```python pdf_group.add_item(self.cross_references[ref]) ``` [`GraphicsContext.add_item()`](https://github.com/py-pdf/fpdf2/blob/a3307f96a0d165831029b3fb644aee5a7ca03328/fpdf/drawing.py#L3618-L3633) uses `clone=True` by default and deep-copies the object: ```python def add_item(self, item, clone=True): if clone: item = deepcopy(item) self.path_items.append(item) ``` An attacker can define `g1` as eight references to `g0`, `g2` as eight references to `g1`, and so on. Each level adds only a small amount of XML, but fpdf2 copies the entire tree from the previous level eight times. The resulting work grows approximately as `8^n`. `ResourceAccessPolicy` d

osv:GHSA-wqw6-wpr3-45rh

fpdf2

Fixed versions: 2.8.8

Complete source record
{
  "id": "7f13e6ce4dd82460ed4ef2ce50951bc33443bfc0dc0d4244d08bc185c7556c5a",
  "url": "https://osv.dev/vulnerability/GHSA-wqw6-wpr3-45rh",
  "method": "structured",
  "payload": {
    "kind": "advisory",
    "title": "fpdf2: Exponential SVG '' expansion causes CPU and memory exhaustion in 'FPDF.image()'",
    "summary": "### Summary fpdf2 expands SVG `` references by deep-copying the complete referenced graphics tree. A small SVG can use nested references to make the number of in-memory objects grow exponentially, causing excessive CPU and memory consumption during `FPDF.image()` processing. This was reproduced with an 895-byte SVG on fpdf2 2.8.7. Under a 128 MB process limit, the input kept the process busy for about 14 seconds before raising `MemoryError`. ### Details The issue is in fpdf2's own SVG reference handling. It does not rely on XML entities, external URLs, local files, or vulnerable behavior in another dependency. When fpdf2 resolves an SVG reference, [`SVGObject.build_xref()`](https://github.com/py-pdf/fpdf2/blob/a3307f96a0d165831029b3fb644aee5a7ca03328/fpdf/svg.py#L1584) passes the referenced object to `GraphicsContext.add_item()`: ```python pdf_group.add_item(self.cross_references[ref]) ``` [`GraphicsContext.add_item()`](https://github.com/py-pdf/fpdf2/blob/a3307f96a0d165831029b3fb644aee5a7ca03328/fpdf/drawing.py#L3618-L3633) uses `clone=True` by default and deep-copies the object: ```python def add_item(self, item, clone=True): if clone: item = deepcopy(item) self.path_items.append(item) ``` An attacker can define `g1` as eight references to `g0`, `g2` as eight references to `g1`, and so on. Each level adds only a small amount of XML, but fpdf2 copies the entire tree from the previous level eight times. The resulting work grows approximately as `8^n`. `ResourceAccessPolicy` d",
    "evidence": "osv:GHSA-wqw6-wpr3-45rh",
    "products": [
      {
        "name": {
          "value": "fpdf2",
          "evidence": "/affected/0/package/name"
        },
        "prerequisites": [],
        "fixed_versions": [
          {
            "value": "2.8.8",
            "evidence": "/affected/0/ranges"
          }
        ],
        "affected_versions": [
          {
            "value": "2.5.0",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.5.1",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.5.2",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.5.3",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.5.4",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.5.5",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.5.6",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.5.7",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.6.0",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.6.1",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.7.0",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.7.1",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.7.2",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.7.3",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.7.4",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.7.5",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.7.6",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.7.7",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.7.8",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.7.9",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.8.1",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.8.2",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.8.3",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.8.4",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.8.5",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.8.6",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.8.7",
            "evidence": "/affected/0/versions"
          }
        ]
      }
    ],
    "severity": "medium",
    "structured": {
      "id": "GHSA-wqw6-wpr3-45rh",
      "aliases": [
        "CVE-2026-114610",
        "GHSA-wqw6-wpr3-45rh"
      ],
      "metrics": [
        {
          "type": "CVSS_V3",
          "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H"
        }
      ],
      "affected": [
        {
          "ranges": [
            {
              "type": "ECOSYSTEM",
              "events": [
                {
                  "introduced": "2.5.0"
                },
                {
                  "fixed": "2.8.8"
                }
              ]
            }
          ],
          "package": {
            "name": "fpdf2",
            "purl": "pkg:pypi/fpdf2",
            "ecosystem": "PyPI"
          },
          "versions": [
            "2.5.0",
            "2.5.1",
            "2.5.2",
            "2.5.3",
            "2.5.4",
            "2.5.5",
            "2.5.6",
            "2.5.7",
            "2.6.0",
            "2.6.1",
            "2.7.0",
            "2.7.1",
            "2.7.2",
            "2.7.3",
            "2.7.4",
            "2.7.5",
            "2.7.6",
            "2.7.7",
            "2.7.8",
            "2.7.9",
            "2.8.1",
            "2.8.2",
            "2.8.3",
            "2.8.4",
            "2.8.5",
            "2.8.6",
            "2.8.7"
          ],
          "database_specific": {
            "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-wqw6-wpr3-45rh/GHSA-wqw6-wpr3-45rh.json"
          }
        }
      ],
      "modified": "2026-10-27T15:00:04.509088444Z",
      "provider": "osv",
      "references": [
        "https://github.com/py-pdf/fpdf2/security/advisories/GHSA-wqw6-wpr3-45rh",
        "https://nvd.nist.gov/vuln/detail/CVE-2026-114610",
        "https://github.com/py-pdf/fpdf2/pull/1889",
        "https://github.com/py-pdf/fpdf2/commit/d7bd1061205d50da6a541dadfdb9d66beb763f2f",
        "https://github.com/py-pdf/fpdf2",
        "https://github.com/py-pdf/fpdf2/releases/tag/2.8.8"
      ],
      "provider_metadata": {
        "cwe_ids": [
          "CWE-400"
        ],
        "severity": "MODERATE",
        "github_reviewed": true,
        "nvd_published_at": "2026-10-22T18:17:28Z",
        "github_reviewed_at": "2026-10-27T14:43:19Z"
      }
    },
    "related_cves": [
      {
        "value": "CVE-2026-114610",
        "evidence": "/aliases"
      }
    ],
    "security_relevant": true,
    "severity_evidence": "/severity/0/score"
  },
  "source_id": "core-osv",
  "document_id": 462801,
  "published_at": "2026-10-27T14:43:19+00:00"
}