PyPI / wrapt / 2.5.2rc1

wrapt 2.5.2rc1

Source
https://github.com/GrahamDumpleton/wrapt
Artifact scanned
wrapt-2.5.2rc1-py3-none-any.whl (wheel · 80.1 KB · SHA-256 3243339e5592…)
Compared with
wrapt-2.5.1-py3-none-any.whl (0 signals introduced since)
Files
17 scanned, 4 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 4 info
Scan time
5.4 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 4 of 4 warn and critical signals; 4 demoted to info.
Disclude version
4.3.0
Scanned (UTC)
2026-10-23 02:39

Signals

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

  1. info warn → info by review dynamic-attribute wrapt/patches.py:103:32

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

                        if attribute in vars(cls):
                            return vars(cls)[attribute]
                    else:
                        return getattr(parent, attribute)
    likely benign LLM, confidence 0.90 Attribute resolution by name through vars() and getattr in wrapt's patch-resolution code.
    Reasoning

    The snippet shows a lookup of an attribute in vars(cls) and a fallback to getattr(parent, attribute). This is ordinary reflection for resolving class attributes along the MRO in a decorator/patching library. The file is wrapt, a well-known legitimate library, and nothing here runs or decodes data.

  2. info warn → info by review dynamic-attribute wrapt/patches.py:348:13

    reach-by-name through `vars.get` (ast pass, confidence 0.60)

        parent = resolve_path(module, path)[2]
        prior = vars(parent).get(attribute, MISSING)
        wrapper = AttributeWrapper(prior, attribute, factory, args, kwargs)
        apply_patch(parent, attribute, wrapper)
    likely benign LLM, confidence 0.90 Reads the original attribute from a parent object's __dict__ before wrapping it.
    Reasoning

    vars(parent).get(attribute, MISSING) reads the prior attribute value so a wrapper can be stored in its place. This is the standard way a monkeypatching library saves and restores the original attribute. It has no execution, network, or encoding behavior.

  3. info warn → info by review dynamic-attribute wrapt/patches.py:840:17

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

                (
                    vars(cls)[attribute]
                    for cls in inspect.getmro(owner)[1:]
                    if attribute in vars(cls)
    likely benign LLM, confidence 0.90 Walks the owner's MRO via vars() to locate an inherited attribute.
    Reasoning

    A generator walks the MRO with inspect.getmro and reads vars(cls)[attribute] to find an inherited attribute. This is normal introspection in a proxy/patching library and is not obfuscation.

  4. info critical → info by review dynamic-import wrapt/proxies.py:379:18

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

        def _import():
            module = __import__(name, fromlist=[""])
    
            if attribute is not None:
    likely benign LLM, confidence 0.85 A deferred __import__ of a module name inside a lazy-import helper in wrapt's proxies.
    Reasoning

    The non-literal __import__(name, fromlist=[""]) sits inside an _import() helper, which matches wrapt's lazy-object-proxy design: the module is imported on first access. The name comes from the library's own proxy setup, not from encoded or remote input. The critical severity reflects the dynamic import pattern, not malicious intent. Without seeing the caller I can't fully rule out an attacker-controlled name, so confidence is not maximal.

Reproduce This Scan

Run disclude locally to verify. These commands scan the published file; the "new in this release" marks come from comparing it with the previous release's file, which they don't repeat. 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.3.0
curl -fsSL -o wrapt-2.5.2rc1-py3-none-any.whl https://files.pythonhosted.org/packages/49/8c/d2ffb8c9f1a5708a67250c3fdb62a378e0db0f8a9f669a97ad205e1cb95a/wrapt-2.5.2rc1-py3-none-any.whl
printf '%s  %s\n' 3243339e559235af90206c049d2282a63e9875ef2b3a9a8981cbfe0292f535e3 wrapt-2.5.2rc1-py3-none-any.whl | shasum -a 256 -c -
unzip -q wrapt-2.5.2rc1-py3-none-any.whl -d pkg
disclude scan --untrusted --severity info pkg