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
8.6 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 7 of 7 warn and critical signals; 7 demoted to info.
Disclude version
4.1.0
Scanned (UTC)
2026-10-21 21:25

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 object used as a test fixture for serialization compatibility.
    Reasoning

    The bytes begin with pickle protocol 5 and reference attr._make.Attribute. This is a test fixture for pickle compatibility of attrs classes, not a malicious payload. The concatenated literal is just a serialized object.

  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 for a serialization test.
    Reasoning

    Same structure as the other fixtures: a pickle protocol 5 stream referencing attr._make.Attribute with a different attribute name. This matches test data for pickling attrs classes and is not executed as a payload.

  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 a pickling test.
    Reasoning

    The bytes are a pickle protocol 5 stream for an attr._make.Attribute, consistent with the sibling fixtures in the same test. They are serialized test data, and nothing in the snippet runs them.

  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 markdown changelog sentence linking to a commit on GitHub.
    Reasoning

    The flagged 'blob' is ordinary prose with a GitHub commit URL and anchor. The base64-like match is a false positive from the raw pass on a URL fragment.

  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.93 Internal code generation in attrs that compiles and evaluates a generated function body.
    Reasoning

    This is attrs' helper that compiles generated method source text into a code object and execs it so tracebacks and linecache work. The script is built by the library itself, not from untrusted input, so the non-literal compile is expected.

  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.93 Evaluates the bytecode of attrs-generated method source in a controlled namespace.
    Reasoning

    This eval runs the bytecode produced by the adjacent compile call on library-generated source, which is the standard code-generation pattern for attrs method creation. Nothing here takes outside input.

  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 Reads the caller's module name from the call stack to assign __module__ on a newly created type.
    Reasoning

    Reading sys._getframe(1).f_globals to set __module__ on a dynamically created class is a common, legitimate technique for matching the caller's module. The 'anti-analysis' co-occurrence with exit/exec/eval is just a file-level heuristic and does not indicate evasion here.

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.1.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 .