PyPI / pypdf / 6.21.0

pypdf 6.21.0

Source
https://github.com/py-pdf/pypdf
Tag scanned
6.21.0
Compared with
6.20.1 (0 signals introduced since)
Files
187 scanned, 110 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 40 info
Scan time
24.3 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-17 04:56

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
    dismissed LLM, confidence 0.90 A GitHub URL path in a FAQ document was mis-flagged as a base64 blob.
    Reasoning

    The flagged string is a GitHub URL path inside a markdown sentence, not an encoded blob. The base64-like match is a false positive from the raw pass.

  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"
    )
    dismissed LLM, confidence 0.90 A constant PDF password padding byte string used in encryption key derivation.
    Reasoning

    The bytes are the standard 32-byte PDF encryption padding string (starting 28 BF 4E 5E 4E 75 8A 41...), a well-known constant defined by the PDF specification and used for RC4/AES key derivation. It is a legitimate constant, not a hidden payload.

  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"
    )
    dismissed LLM, confidence 0.90 The PDF standard padding constant written as hex escapes.
    Reasoning

    Same PDF standard padding constant as the sibling finding. The hex-escape match is a raw-pass artifact of a legitimate specification value.

  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"
    )
    dismissed LLM, confidence 0.90 Second half of the PDF standard padding constant.
    Reasoning

    Continuation line of the same PDF padding constant defined in the spec. No execution or decoding of the bytes occurs here.

  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.80 Checks whether a visitor keyword argument was supplied, using locals() lookup.
    Reasoning

    locals() is read to check whether a visitor argument was passed in layout mode, a common pattern for detecting optional parameters. It reads local variables only and does not execute or fetch external code, though it is a slightly unusual idiom.

  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.90 Bounded zlib decompression of PDF stream data.
    Reasoning

    zlib.decompressobj with max_length is the standard bounded FlateDecode decompression used when parsing PDF streams. The output limit is a deliberate safety control against decompression bombs.

  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.85 Byte-value lookup tuple used when parsing inline image data.
    Reasoning

    The bytes are a tuple of byte values used for membership tests when parsing inline image data, consistent with PDF/JPEG marker handling. It is a lookup table, 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.85 Continuation of a byte-value lookup table in inline image parsing.
    Reasoning

    Continuation of the same byte-value lookup table in inline image parsing. The raw-pass hex match reflects the literal form, not a hidden payload.

  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
    dismissed LLM, confidence 0.90 Typographic ligature in a sample text file.
    Reasoning

    The word 'misfits' uses the Unicode fi ligature (U+FB01), which typography in the source text produces. It is a text resource, not code, so there is no identifier spoofing risk.

  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.
    dismissed LLM, confidence 0.90 Typographic ligature in a sample text file.
    Reasoning

    'differently' uses the ff ligature (U+FB00) from typeset text. This is a sample text resource with no code or identifier context.

  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
    dismissed LLM, confidence 0.90 Typographic ligature in a layout test fixture.
    Reasoning

    Same fi ligature in a test fixture for layout extraction. The mixed-script flag is a false positive on ordinary typeset 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.
    dismissed LLM, confidence 0.90 Typographic ligature in a layout test fixture.
    Reasoning

    Same ff ligature in a layout test fixture. It is ordinary text, not an identifier.

  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.
    dismissed LLM, confidence 0.90 Typographic ligature in a text test fixture.
    Reasoning

    Same fi ligature in a text fixture for font and layout tests. No code context and no spoofing.

  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.
    dismissed LLM, confidence 0.90 Typographic ligature in a text test fixture.
    Reasoning

    Same ff ligature in a text test 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.93 Hex dump of JPEG image bytes stored as a long text line in a test resource.
    Reasoning

    A single 82 KB line of hex-encoded JPEG header and quantization data in a resource text file. This is a test fixture for image handling, and long hex lines are a known artifact of dumping binary data, not obfuscation.

  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 Lorem ipsum sample text containing a typographic fi ligature character.
    Reasoning

    The mixed-script flag comes from the typographic ligature 'fi' (U+FB01) in ordinary lorem ipsum prose. Raw-pass unicode checks produce many false positives on such text, and this is plain document content.

  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.85 Test helper reads its caller's frame name to verify a compatibility shim.
    Reasoning

    inspect.currentframe is used in a test to check the caller name for a backwards-compatible font substitution path. This is a normal way to test call-site behavior in a PDF library and has no sign of malicious use.

  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.92 Test fixture of binary CCITT-encoded image bytes written as escaped literals.
    Reasoning

    A bytes literal of CCITT fax encoded image data used as the expected output and input for decoder tests. Binary fixture data in tests is expected.

  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.90 Repeated binary image test fixture in the same test function.
    Reasoning

    Same test image fixture as the previous finding, flagged again on a different escape count. It is a benign binary test payload.

  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.90 Repeated binary image test fixture in the same test function.
    Reasoning

    Same test image fixture as the previous finding, flagged again on a different escape count. It is a benign binary test payload.

  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.92 Continuation of a binary image test fixture literal.
    Reasoning

    Continuation of the same binary image test fixture. The bytes are image structure data used for decoder validation.

  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.90 JBIG2 globals stream bytes used as a decoder test input.
    Reasoning

    A JBIG2 globals segment as a bytes literal with a noqa marker, used as decoder input in a test. This is standard test data for a PDF image codec.

  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 Inline PDF image test fixture containing JPEG bytes.
    Reasoning

    An inline image containing a JPEG header with a text comment, built as an expected PDF content fragment. Benign test fixture for inline image handling.

  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 data constant used as a Flate image test fixture.
    Reasoning

    A constant of flate-compressed-looking raw pixel data used for image decode tests. It is a plain binary test fixture with no execution or hiding behavior.

  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.80 Test temporarily installs a trace function around a PDF object clone.
    Reasoning

    sys.settrace is set around a clone call in a test, with the previous trace restored in a finally block. It looks like a test that checks recursion or call behavior during cloning. It is unusual, but it is scoped and cleaned up, which fits a test rather than a dropper.

  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.80 Cleanup restoring the prior trace function after a clone test.
    Reasoning

    Restores the previous trace function and re-enables gc in a finally block, the cleanup half of the same test-scoped tracing. It is consistent with a benign test harness.

  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 Embedded PNG image bytes used as expected test data in an assertion.
    Reasoning

    The bytes literal is a PNG file header (\x89PNG), IHDR chunk, IDAT and IEND markers: a genuine embedded test image fixture. High escape density is expected for binary test data in a test file asserting image data equality. No execution or hidden code.

  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 Test helper temporarily installs a call-counting profiler around a function under test.
    Reasoning

    Saving the previous profile hook and installing a call-counting profiler around a function call is a standard test utility for counting calls. The sys.setprofile use is a profiling tool, not malicious; it is restored in a finally block.

  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 Restores the previous profiler hook after the call-counting helper runs.
    Reasoning

    This is the paired restore of the previous profile function in the finally block, matching the install at line 255. Legitimate profiler cleanup in a test helper.

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.0
disclude scan --severity info --diff 6.20.1 .