PyPI / attrs / 26.1.0

attrs 26.1.0

Source
https://github.com/python-attrs/attrs
Tag scanned
26.1.0
Compared with
25.4.0 (3 signals introduced since)
Files
84 scanned, 25 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 10 info
Scan time
7.2 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 7 of 7 warn and critical signals; 7 demoted to info.
Disclude version
4.0.0
Scanned (UTC)
2026-10-14 18:14

Signals

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

  1. info warn → info by review payload-bytes-literal tests/test_make.py:2437:9 new in this release

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

        X = (
            b"\x80\x05\x95_\x00\x00\x00\x00\x00\x00\x00\x8c\nattr._make\x94\x8c\tAttrib"
            b"ute\x94\x93\x94)\x81\x94(\x8c\x01x\x94h\x00\x8c\x08_Nothing\x94\x93"
            b"\x94K\x01\x85\x94R\x94N\x88\x88N\x88NN\x88}\x94\x8c\x08builtins\x94"
    likely benign LLM, confidence 0.90 A pickled attrs Attribute fixture used in the pickling tests.
    Reasoning

    This is a pickle protocol-5 byte string (header \x80\x05, references to attr._make.Attribute and builtins). It is a test fixture for checking that attrs classes unpickle correctly across versions. Test fixtures of this kind are expected to contain binary data.

  2. info warn → info by review payload-bytes-literal tests/test_make.py:2443:9 new in this release

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

        Y = (
            b"\x80\x05\x95b\x00\x00\x00\x00\x00\x00\x00\x8c\nattr._make\x94\x8c\tAttrib"
            b"ute\x94\x93\x94)\x81\x94(\x8c\x02_y\x94h\x00\x8c\x08_Nothing\x94"
            b"\x93\x94K\x01\x85\x94R\x94N\x88\x88N\x88NN\x88}\x94\x8c\x08builtins"
    likely benign LLM, confidence 0.90 A pickled attrs Attribute fixture used in the pickling tests.
    Reasoning

    Same pattern as the other fixtures: a pickle byte string referencing attr._make.Attribute and builtins, with a serialized field name. It is a regression fixture in the test suite and has no execution path.

  3. info warn → info by review payload-bytes-literal tests/test_make.py:2449:9 new in this release

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

        Z = (
            b"\x80\x05\x95c\x00\x00\x00\x00\x00\x00\x00\x8c\nattr._make\x94\x8c\tAttrib"
            b"ute\x94\x93\x94)\x81\x94(\x8c\x01z\x94h\x00\x8c\x08_Nothing\x94\x93"
            b"\x94K\x01\x85\x94R\x94N\x88\x88N\x88NN\x88}\x94\x8c\x08builtins\x94"
    likely benign LLM, confidence 0.90 A pickled attrs Attribute fixture used in the pickling tests.
    Reasoning

    This is a pickle fixture of the same shape, used to test deserialization of attrs objects. The byte literal is test data and is not executed as a payload.

  4. info long-line docs/api.rst:156:1

    line length 508 characters (raw pass, confidence 0.50)

          (Attribute(name='x', default=NOTHING, validator=None, repr=True, eq=True, eq_key=None, order=True, order_key=None, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False, inherited=False, on_setattr=None, alias='x'), Attribute(name='y', default=NOTHING, validator=None, repr=True
  5. info long-line docs/api.rst:175:1

    line length 518 characters (raw pass, confidence 0.50)

          {'x': Attribute(name='x', default=NOTHING, validator=None, repr=True, eq=True, eq_key=None, order=True, order_key=None, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False, inherited=False, on_setattr=None, alias='x'), 'y': Attribute(name='y', default=NOTHING, validator=None,
  6. info long-line docs/api.rst:588:1

    line length 504 characters (raw pass, confidence 0.50)

            ValueError: ("'email' must match regex '(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\\\.[a-zA-Z0-9-.]+$)' ('user@example.com@test.com' doesn't)", Attribute(name='email', default=NOTHING, validator=<matches_re validator for pattern re.compile('(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$)')>, repr=True, cmp=True, has
  7. info warn → info by review encoding-base64 docs/names.md:84:169

    base64-like blob (67 bytes, compression ratio 0.94) (raw pass, confidence 0.60)

    As a little easter egg and to save ourselves some typing, we've also [added]https://github.com/python-attrs/attrs/commit/88aa1c897dfe2ee4aa987e4a56f2ba1344a17238#diff-4fc63db1f2fcb7c6e464ee9a77c3c74e90dd191d1c9ffc3bdd1234d3a6663dc0R48 an alias called `attr.dataclass` that just set `auto_attribs=True`.
    dismissed LLM, confidence 0.97 A commit-hash URL in the attrs naming docs was flagged as a base64 blob.
    Reasoning

    The raw-pass base64 hit is a GitHub commit URL with a 40-character hex hash fragment in a markdown link. It is prose documentation, not an encoded payload, and the raw pass has a high false-positive rate.

  8. info warn → info by review dynamic-execution src/attr/_make.py:226:16

    `compile` called on a non-literal expression (ast pass, confidence 0.70)

        """
        bytecode = compile(script, filename, "exec")
        eval(bytecode, globs, locs)
    likely benign LLM, confidence 0.90 attrs compiles and evals its own generated method source at runtime.
    Reasoning

    This is attrs' own code-generation helper: it compiles and evals source text it builds from its internal templates to create methods such as __init__ and __repr__. That is a known, legitimate use in a library that generates code at runtime. The non-literal argument is expected here, not attacker-controlled input.

  9. info warn → info by review dynamic-execution src/attr/_make.py:227:5

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

        bytecode = compile(script, filename, "exec")
        eval(bytecode, globs, locs)
    likely benign LLM, confidence 0.90 The paired eval executes attrs' generated bytecode.
    Reasoning

    The eval call executes the bytecode produced by the compile on the line above, as part of attrs' internal method generation. The inputs are library-generated, so this matches the pattern of a legitimate code generator.

  10. info critical → info by review frame-introspection src/attr/_make.py:3285:28

    `sys._getframe` — call-stack frame introspection — file also calls `sys.exit`/`exec`/`eval` (anti-analysis shape) (ast pass, confidence 0.85)

        with contextlib.suppress(AttributeError, ValueError):
            type_.__module__ = sys._getframe(1).f_globals.get(
                "__name__", "__main__"
            )
    likely benign LLM, confidence 0.90 attrs reads the caller's module name via frame introspection to set __module__.
    Reasoning

    sys._getframe(1).f_globals is a standard idiom for reading the calling module's __name__, which attrs uses to set __module__ on classes it creates. The critical severity comes from the anti-analysis shape heuristic, which matches the presence of exec/eval elsewhere in the same file. Nothing here hides behaviour or evades analysis.

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/python-attrs/attrs attrs && cd attrs
git checkout 26.1.0
disclude scan --severity info --diff 25.4.0 .