PyPI / pypdf / 6.21.1

pypdf 6.21.1

Source
https://github.com/py-pdf/pypdf
Tag scanned
6.21.1
Compared with
6.21.0 (0 signals introduced since)
Files
187 scanned, 110 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 40 info
Scan time
19.9 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 28 of 29 warn and critical signals; 29 demoted to info.
Disclude version
4.0.0
Scanned (UTC)
2026-10-18 05:41

Signals

Ordered by severity, then signals introduced in this release. Hidden characters are shown as ⟨U+…⟩.

  1. info warn → info by review encoding-base64 docs/meta/faq.md:21:288

    base64-like blob (66 bytes, compression ratio 1.17) (raw pass, confidence 0.60)

    ://github.com/Giacomo-De-Florio-Dev/Make_Your_PDF_Safe/tree/ec439f92243d12d54ae024668792470c6b40ee96/MakeYourPDFsafe_V1.3/PyPDF2). That
    likely benign LLM, confidence 0.90 A GitHub URL in a markdown documentation file, flagged as a base64-like blob.
    Reasoning

    The flagged 'base64-like blob' is a long GitHub URL path with a commit hash inside a markdown FAQ. Raw pattern matches on URL characters are a known false-positive shape, and there is no decoding or execution.

  2. info warn → info by review payload-bytes-literal pypdf/_encryption.py:114:5

    concatenated bytes literal contains 32 `\xNN` escapes (100% of content) — binary payload shape (ast pass, confidence 0.85)

    _PADDING = (
        b"\x28\xbf\x4e\x5e\x4e\x75\x8a\x41\x64\x00\x4e\x56\xff\xfa\x01\x08"
        b"\x2e\x2e\x00\xb6\xd0\x68\x3e\x80\x2f\x0c\xa9\xfe\x64\x53\x69\x7a"
    )
    likely benign LLM, confidence 0.95 The standard 32-byte PDF encryption padding constant assigned to _PADDING.
    Reasoning

    The 32-byte sequence 28 BF 4E 5E 4E 75 8A 41 ... is the standard PDF encryption padding string defined by the PDF specification. It is a constant used in RC4/AES key derivation in a PDF library, so the binary shape is expected.

  3. info warn → info by review encoding-hex pypdf/_encryption.py:114:7

    16 consecutive `\xNN` escapes (entropy 3.7 bits/byte) (raw pass, confidence 0.65)

    _PADDING = (
        b"\x28\xbf\x4e\x5e\x4e\x75\x8a\x41\x64\x00\x4e\x56\xff\xfa\x01\x08"
        b"\x2e\x2e\x00\xb6\xd0\x68\x3e\x80\x2f\x0c\xa9\xfe\x64\x53\x69\x7a"
    )
    likely benign LLM, confidence 0.93 Hex escapes of the PDF encryption padding constant.
    Reasoning

    This raw hex-escape finding covers the same well-known PDF padding constant. It is a fixed cryptographic constant, not an obfuscated payload.

  4. info warn → info by review encoding-hex pypdf/_encryption.py:115:7

    16 consecutive `\xNN` escapes (entropy 3.9 bits/byte) (raw pass, confidence 0.65)

        b"\x28\xbf\x4e\x5e\x4e\x75\x8a\x41\x64\x00\x4e\x56\xff\xfa\x01\x08"
        b"\x2e\x2e\x00\xb6\xd0\x68\x3e\x80\x2f\x0c\xa9\xfe\x64\x53\x69\x7a"
    )
    likely benign LLM, confidence 0.93 Second half of the PDF encryption padding constant.
    Reasoning

    This is the second half of the same PDF padding constant, flagged by the raw pass. It is a standard specification value.

  5. info warn → info by review dynamic-attribute pypdf/_page.py:2279:20

    reach-by-name through `locals` (ast pass, confidence 0.60)

                ):
                    if locals()[visitor]:
                        logger_warning(
                            "Argument %(visitor)s is ignored in layout mode",
    likely benign LLM, confidence 0.85 Looks up a visitor parameter by name through locals() to emit a warning.
    Reasoning

    locals() is used to check whether a named visitor argument was passed in order to warn that it is ignored in layout mode. This is a local-variable lookup for a legitimate parameter check, with no dynamic execution or hidden payload.

  6. info warn → info by review decoder-decompress-payload pypdf/filters.py:95:20

    file imports decoder module(s) binascii, zlib, base64 and calls `.decompress()` — embedded payload decompressed at runtime (ast pass, confidence 0.75)

    def _decompress_with_limit(data: bytes) -> bytes:
        decompressor = zlib.decompressobj()
        configuration = get_configuration()
        result = decompressor.decompress(data, max_length=configuration.zlib_maximum_output_length)
    likely benign LLM, confidence 0.92 Bounded zlib decompression of PDF stream data.
    Reasoning

    This is standard FlateDecode decompression of PDF stream data, bounded by max_length from configuration. It is ordinary PDF parsing and decompression, not a runtime-embedded payload.

  7. info warn → info by review payload-bytes-literal pypdf/generic/_image_inline.py:195:13

    concatenated bytes literal contains 38 `\xNN` escapes (100% of content) — binary payload shape (ast pass, confidence 0.85)

            elif c in (
                b"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc9\xca\xcb\xcc\xcd\xce\xcf"
                b"\xda\xdb\xdc\xdd\xde\xdf"
                b"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xfe"
    likely benign LLM, confidence 0.90 A concatenated bytes lookup table used in inline image parsing.
    Reasoning

    The bytes literal lists byte values in a tuple used for inline image parsing or marker classification. The content is a fixed table of byte values for image format handling, not an executable payload.

  8. info warn → info by review encoding-hex pypdf/generic/_image_inline.py:197:15

    17 consecutive `\xNN` escapes (entropy 4.1 bits/byte) (raw pass, confidence 0.65)

                b"\xda\xdb\xdc\xdd\xde\xdf"
                b"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xfe"
            ):
                c = read(2)
    likely benign LLM, confidence 0.90 Continuation of a byte-value lookup table in inline image parsing.
    Reasoning

    This raw hex finding is the continuation of the same byte lookup table in the inline image parser. It is a legitimate constant table.

  9. info warn → info by review unicode-mixed-script resources/crazyones.txt:3:30

    identifier `misfits` mixes scripts: Latin + Other (raw pass, confidence 0.80)

    October 14, 1998
    Heres to the crazy ones. The misfits. The rebels. The troublemakers.
    The round pegs in the square holes.
    The ones who see things differently. Theyre not fond of rules. And
    likely benign LLM, confidence 0.95 Typographic fi ligature in the word 'misfits' within a quote fixture.
    Reasoning

    The 'fi' in 'misfits' is the Unicode fi ligature (U+FB01), which typesetting and PDF text commonly produce. It is ordinary prose in a text test fixture.

  10. info warn → info by review unicode-mixed-script resources/crazyones.txt:5:25

    identifier `differently` mixes scripts: Latin + Other (raw pass, confidence 0.80)

    The round pegs in the square holes.
    The ones who see things differently. Theyre not fond of rules. And
    they have no respect for the status quo. You can quote them,
    disagree with them, glorify or vilify them.
    likely benign LLM, confidence 0.95 Typographic ff ligature in the word 'differently' within a quote fixture.
    Reasoning

    The 'ff' in 'differently' is the Unicode ff ligature (U+FB00), a common artifact of typeset text. It is not a homoglyph attack.

  11. info warn → info by review unicode-mixed-script resources/crazyones_layout_vertical_space.txt:4:34

    identifier `misfits` mixes scripts: Latin + Other (raw pass, confidence 0.80)

    
       Heres to the crazy ones.  The misfits.  The rebels.  The troublemakers.
           The round pegs in the square holes.
       The ones who see things differently.  Theyre not fond of rules.  And
    likely benign LLM, confidence 0.95 Typographic fi ligature in a layout test fixture.
    Reasoning

    This is the same fi ligature in 'misfits' in a layout test fixture of the same quote. It is ordinary text.

  12. info warn → info by review unicode-mixed-script resources/crazyones_layout_vertical_space.txt:6:28

    identifier `differently` mixes scripts: Latin + Other (raw pass, confidence 0.80)

           The round pegs in the square holes.
       The ones who see things differently.  Theyre not fond of rules.  And
           they have no respect for the status quo.  You can quote them,
           disagree with them, glorify or vilify them.
    likely benign LLM, confidence 0.95 Typographic ff ligature in a layout test fixture.
    Reasoning

    This is the same ff ligature in 'differently' in a layout test fixture. It is ordinary typeset text.

  13. info warn → info by review unicode-mixed-script resources/crazyones_layout_vertical_space_font_height_weight.txt:4:34

    identifier `misfits` mixes scripts: Latin + Other (raw pass, confidence 0.80)

    
       Heres to the crazy ones.  The misfits.  The rebels.  The troublemakers.
           The round pegs in the square holes.
    likely benign LLM, confidence 0.95 Typographic fi ligature in a font-variant text fixture.
    Reasoning

    This fi ligature in 'misfits' appears in another text layout fixture. It is ordinary typeset text.

  14. info warn → info by review unicode-mixed-script resources/crazyones_layout_vertical_space_font_height_weight.txt:7:28

    identifier `differently` mixes scripts: Latin + Other (raw pass, confidence 0.80)

    
       The ones who see things differently.  Theyre not fond of rules.  And
           they have no respect for the status quo.  You can quote them,
           disagree with them, glorify or vilify them.
    likely benign LLM, confidence 0.95 Typographic ff ligature in a font-variant text fixture.
    Reasoning

    This ff ligature in 'differently' appears in another text layout fixture. It is ordinary typeset text.

  15. info warn → info by review long-line resources/jpeg.txt:1:1

    line length 82804 characters (raw pass, confidence 0.65)

    ffd8ffe000104a46494600010100000100010000ffdb0043000302020302020303030304030304050805050404050a070706080c0a0c0c0b0a0b0b0d0e12100d0e110e0b0b1016101113141515150c0f171816141812141514ffdb00430103040405040509050509140d0b0d1414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414ffc2
    likely benign LLM, confidence 0.95 Long hex dump of JPEG header bytes stored in a text fixture.
    Reasoning

    A single very long line of hex-encoded JPEG header bytes in a text resource file. This is test data in a resource file, typical of a PDF library's fixtures; no execution or concealment.

  16. info warn → info by review unicode-mixed-script resources/multicolumn-lorem-ipsum.txt:8:52

    identifier `filled` mixes scripts: Other + Latin (raw pass, confidence 0.80)

    This  is  a  sample  document  with  two  columns  filled              molestie vitae, placerat a, molestie nec, leo.  Maece-
    with Lorem Ipsum text.                                                nas lacinia.  Nam ipsum ligula, eleifend at, accumsan
    dismissed LLM, confidence 0.95 Typographic fi ligature in lorem ipsum sample text.
    Reasoning

    The 'fi' is a standard typographic ligature (U+FB01) common in text from PDFs or word processors; it is in lorem ipsum sample text, not an identifier used in code.

  17. info warn → info by review frame-introspection tests/generic/test_font.py:290:34

    `inspect.currentframe` — call-stack frame introspection (ast pass, confidence 0.70)

        def build_reversed_min(_self: table__c_m_a_p) -> Any:
            caller = cast(FrameType, inspect.currentframe()).f_back
            caller_name = cast(FrameType, caller).f_code.co_name
            # Check the backwards-compatible substitution works when calling from pypdf
    likely benign LLM, confidence 0.90 Test helper inspects its caller's frame name to verify compatibility behavior.
    Reasoning

    Test code for a PDF library uses inspect.currentframe() to check the caller name for backwards-compatible substitution. Ordinary introspection in a test, not malicious.

  18. info unicode-homoglyph tests/test_cmap.py:196:18

    identifier `α` contains homoglyph candidates: α (03B1)→a (in string/comment) (raw pass, confidence 0.35)

        txt = reader.pages[0].extract_text()  # no error
        for pat in ("α", "β", "γ", "ϕ", "φ", "ℏ", "∫", "∂", "·", "×"):
            assert pat in txt
        # actually the ϕ and φ seems to be crossed in latex
  19. info warn → info by review payload-bytes-literal tests/test_filters.py:253:9

    concatenated bytes literal contains 104 `\xNN` escapes (99% of content) — binary payload shape (ast pass, confidence 0.85)

        assert CCITTFaxDecode.decode(data, parameters) == (
            b"II*\x00\x08\x00\x00\x00\x08\x00\x00\x01\x04\x00\x01\x00\x00\x00\x11\x00"
            b"\x00\x00\x01\x01\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x01"
            b"\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\x03\x01\x03\x00\x01\x00"
    likely benign LLM, confidence 0.93 Binary CCITT image fixture bytes used in a decode test.
    Reasoning

    Bytes literal of a TIFF/CCITT fax test image split across lines, consistent with test fixture data for a PDF filter test. Expected binary shape.

  20. info warn → info by review payload-bytes-literal tests/test_filters.py:788:9

    concatenated bytes literal contains 67 `\xNN` escapes (99% of content) — binary payload shape (ast pass, confidence 0.85)

        image_data = (
            b'\x00\x00\x00\x010\x00\x01\x00\x00\x00\x13\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x06"'
            b'\x00\x01\x00\x00\x00\x1c\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x9f\xa8_\xff\xac'
    likely benign LLM, confidence 0.93 Duplicate report of the same binary image fixture.
    Reasoning

    Same binary image fixture as the preceding finding, a duplicate report for the same test data. Benign.

  21. info warn → info by review payload-bytes-literal tests/test_filters.py:788:9

    bytes literal contains 34 `\xNN` escapes (99% of content) — binary payload shape (ast pass, confidence 0.85)

        image_data = (
            b'\x00\x00\x00\x010\x00\x01\x00\x00\x00\x13\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x06"'
            b'\x00\x01\x00\x00\x00\x1c\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x9f\xa8_\xff\xac'
    likely benign LLM, confidence 0.93 Duplicate report of the same binary image fixture.
    Reasoning

    Same binary image fixture as the preceding finding, a duplicate report for the same test data. Benign.

  22. info warn → info by review payload-bytes-literal tests/test_filters.py:789:9

    bytes literal contains 33 `\xNN` escapes (99% of content) — binary payload shape (ast pass, confidence 0.85)

            b'\x00\x00\x00\x010\x00\x01\x00\x00\x00\x13\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x06"'
            b'\x00\x01\x00\x00\x00\x1c\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x9f\xa8_\xff\xac'
    
        )
    likely benign LLM, confidence 0.93 Continuation of binary image fixture bytes in tests.
    Reasoning

    Continuation of the same binary image test fixture used for PDF filter decoding. Benign.

  23. info warn → info by review payload-bytes-literal tests/test_filters.py:792:21

    bytes literal contains 32 `\xNN` escapes (98% of content) — binary payload shape (ast pass, confidence 0.85)

        )
        jbig2_globals = b"\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x18\x00\x00\x03\xff\xfd\xff\x02\xfe\xfe\xfe\x00\x00\x00\x01\x00\x00\x00\x01R\xd0u7\xff\xac"  # noqa: E501
    
        # Validation: Is our image data valid?
    likely benign LLM, confidence 0.92 JBIG2 globals binary fixture in a test.
    Reasoning

    JBIG2 globals binary blob in a test, with a noqa comment for line length. Test fixture data.

  24. info warn → info by review payload-bytes-literal tests/test_filters.py:1086:9

    concatenated bytes literal contains 780 `\xNN` escapes (88% of content) — binary payload shape (ast pass, confidence 0.85)

        image_data = (
            b"\nBI\n  /W 16\n  /H 16\n  /CS /G\n  /BPC 8\n  /F [/DCT]\nID\n"
            b"\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x01,\x01,\x00\x00\xff\xfe\x00\x13Created with GIMP\xff\xe2"
    likely benign LLM, confidence 0.93 Embedded JPEG inline image fixture in a test.
    Reasoning

    Inline image data with JFIF header bytes embedded in a PDF content stream test. Test fixture.

  25. info warn → info by review payload-bytes-literal tests/test_filters.py:1288:5

    concatenated bytes literal contains 310 `\xNN` escapes (100% of content) — binary payload shape (ast pass, confidence 0.85)

    _FLATE_IMAGE_DATA = (
        b"\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
        b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00"
    likely benign LLM, confidence 0.93 Raw pixel fixture bytes for a Flate image test.
    Reasoning

    Raw pixel data for a Flate-compressed image test fixture. Expected binary test data.

  26. info warn → info by review frame-introspection tests/test_generic.py:1287:5

    `sys.settrace` — call-stack frame introspection (ast pass, confidence 0.70)

        previous_trace = sys.gettrace()
        sys.settrace(trace)
        try:
            clone = container.clone(writer)
    likely benign LLM, confidence 0.90 Test temporarily installs a trace function around a clone call.
    Reasoning

    Test sets a trace function around a clone operation to check garbage-collection or tracing behavior, restoring the previous trace afterward. Ordinary test instrumentation.

  27. info warn → info by review frame-introspection tests/test_generic.py:1291:9

    `sys.settrace` — call-stack frame introspection (ast pass, confidence 0.70)

        finally:
            sys.settrace(previous_trace)
            if gc_was_enabled:
                gc.enable()
    likely benign LLM, confidence 0.90 Restores the previous trace function after a test.
    Reasoning

    The finally block restores the previous trace function after the test, paired with the settrace call above. Benign test cleanup.

  28. info warn → info by review payload-bytes-literal tests/test_images.py:723:13

    concatenated bytes literal contains 43 `\xNN` escapes (84% of content) — binary payload shape (ast pass, confidence 0.85)

            assert images["~0~"].data == (
                b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x02\x00\x00\x00\x01\x08\x02\x00\x00\x00{@\xe8\xdd\x00\x00\x00\x0f"
                b"IDATx\x9cc\xe8\xee\xee\xfe\xf7\xef\x1f\x00\x0e \x04\x9cpr_\x96\x00\x00\x00\x00IEND\xaeB`\x82"
            )
    likely benign LLM, confidence 0.95 A test fixture embedding a small PNG image as a bytes literal.
    Reasoning

    The bytes literal is a valid PNG file header (\x89PNG signature, IHDR, IDAT, IEND chunks) inside a test asserting image data equality. Heavy \x escapes are the normal way to embed a binary fixture in a Python test. No execution or exfiltration behavior is present.

  29. info unicode-mixed-script tests/test_text_extraction.py:1238:23

    identifier `ابحرمAB` mixes scripts: Arabic + Latin (in string/comment) (raw pass, confidence 0.40)

            pytest.param("AB ابحرم", "AB مرحبا", id="latin-before"),
            pytest.param("ابحرمAB", "مرحباAB", id="latin-after"),
        ],
    )
  30. info unicode-mixed-script tests/test_text_extraction.py:1238:39

    identifier `مرحباAB` mixes scripts: Arabic + Latin (in string/comment) (raw pass, confidence 0.40)

            pytest.param("AB ابحرم", "AB مرحبا", id="latin-before"),
            pytest.param("ابحرمAB", "مرحباAB", id="latin-after"),
        ],
    )
  31. info unicode-mixed-script tests/test_xmp.py:1065:11

    identifier `fooↂzz` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

            # Non-hex digits, a marker at the end and a truncated escape are all kept as-is.
            ("fooↂzz", {"fooↂzz": "val"}),
            ("fooↂ", {"fooↂ": "val"}),
            ("fooↂ0", {"fooↂ0": "val"}),
  32. info unicode-mixed-script tests/test_xmp.py:1065:24

    identifier `fooↂzz` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

            # Non-hex digits, a marker at the end and a truncated escape are all kept as-is.
            ("fooↂzz", {"fooↂzz": "val"}),
            ("fooↂ", {"fooↂ": "val"}),
            ("fooↂ0", {"fooↂ0": "val"}),
  33. info unicode-mixed-script tests/test_xmp.py:1066:11

    identifier `fooↂ` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

            ("fooↂzz", {"fooↂzz": "val"}),
            ("fooↂ", {"fooↂ": "val"}),
            ("fooↂ0", {"fooↂ0": "val"}),
            # A well-formed escape is still decoded (Adobe stores "my car" this way).
  34. info unicode-mixed-script tests/test_xmp.py:1066:22

    identifier `fooↂ` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

            ("fooↂzz", {"fooↂzz": "val"}),
            ("fooↂ", {"fooↂ": "val"}),
            ("fooↂ0", {"fooↂ0": "val"}),
            # A well-formed escape is still decoded (Adobe stores "my car" this way).
  35. info unicode-mixed-script tests/test_xmp.py:1067:11

    identifier `fooↂ0` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

            ("fooↂ", {"fooↂ": "val"}),
            ("fooↂ0", {"fooↂ0": "val"}),
            # A well-formed escape is still decoded (Adobe stores "my car" this way).
            ("myↂ0020car", {"my car": "val"}),
  36. info unicode-mixed-script tests/test_xmp.py:1067:23

    identifier `fooↂ0` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

            ("fooↂ", {"fooↂ": "val"}),
            ("fooↂ0", {"fooↂ0": "val"}),
            # A well-formed escape is still decoded (Adobe stores "my car" this way).
            ("myↂ0020car", {"my car": "val"}),
  37. info unicode-mixed-script tests/test_xmp.py:1069:11

    identifier `myↂ0020car` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

            # A well-formed escape is still decoded (Adobe stores "my car" this way).
            ("myↂ0020car", {"my car": "val"}),
        ],
    )
  38. identifier `AאA` mixes scripts: Latin + Hebrew (in string/comment) (raw pass, confidence 0.40)

            font=font,
            text_operands="AאA",
            font_size=12,
            rtl_dir=False,
  39. info warn → info by review frame-introspection tests/utils.py:255:5

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

        previous_profile = sys.getprofile()
        sys.setprofile(count_calls)
        try:
            result = func(*args, **kwargs)
    likely benign LLM, confidence 0.90 A test helper that temporarily installs a call-counting profiler around a function call.
    Reasoning

    The function saves the previous profiler, installs a call-counting profile function, runs the target, and restores it. This is a standard test helper for counting calls. sys.setprofile is not malicious here, and the finding's 'frame introspection' label overstates it.

  40. info warn → info by review frame-introspection tests/utils.py:259:9

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

        finally:
            sys.setprofile(previous_profile)
        return result, calls
    likely benign LLM, confidence 0.90 The finally-block restore of the previous profile function in a test helper.
    Reasoning

    This is the restore step in the finally block that resets the profiler saved earlier. It pairs with the install at line 255 in a clean try/finally pattern, which is legitimate test scaffolding.

Reproduce This Scan

Run disclude locally to verify. Add --format sarif for SARIF output. Add --llm (with an API key in the environment) to include the LLM review.

cargo install disclude --version 4.0.0
git clone https://github.com/py-pdf/pypdf pypdf && cd pypdf
git checkout 6.21.1
disclude scan --severity info --diff 6.21.0 .