PyPI / wrapt / 2.5.2rc1

wrapt 2.5.2rc1

Source
https://github.com/GrahamDumpleton/wrapt
Tag scanned
2.5.2rc1
Compared with
2.5.1 (0 signals introduced since)
Files
166 scanned, 47 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 26 info
Scan time
19.8 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 26 of 26 warn and critical signals; 26 demoted to info.
Disclude version
4.1.0
Scanned (UTC)
2026-10-21 23:41

Signals

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

  1. info warn → info by review frame-introspection blog/09-performance-overhead-of-using-decorators.md:103:1

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

    
    sys.setprofile(tracer)
    
    function()
    likely benign LLM, confidence 0.85 Markdown tutorial example using sys.setprofile to measure decorator call overhead.
    Reasoning

    A blog post's embedded Python example calls sys.setprofile(tracer) to illustrate profiling overhead. It is teaching material, not hidden or malicious code.

  2. info warn → info by review frame-introspection blog/10-performance-overhead-when-applying-decorators-to-methods.md:90:1

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

    
    sys.setprofile(tracer)
    
    instance.method()
    likely benign LLM, confidence 0.85 Markdown tutorial example wrapping method calls with a sys.setprofile tracer.
    Reasoning

    The embedded example installs a profiler hook around a method call to demonstrate performance measurement in a blog article. This is a legitimate illustrative pattern.

  3. info critical → info by review dynamic-import blog/13-ordering-issues-when-monkey-patching-in-python.md:105:9

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

        def _load_and_execute(target_module):
            __import__(name)
            patch_module = sys.modules[name]
            getattr(patch_module, 'apply_patch')(target_module)
    likely benign LLM, confidence 0.80 Markdown example helper that dynamically imports a patch module by name.
    Reasoning

    The __import__(name) call sits in a blog illustration of monkey-patching order problems. It is a demonstration snippet, not executed code in the project.

  4. info critical → info by review dynamic-execution docs/conf.py:55:9

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

        if isinstance(node, ast.FunctionDef) and node.name == "_format_version":
            exec(compile(ast.Module(body=[node], type_ignores=[]), "<v>", "exec"), _ns)
        elif isinstance(node, ast.Assign) and any(
            getattr(t, "id", None) in ("__version_info__", "__version__")
    likely benign LLM, confidence 0.85 Sphinx config that extracts version definitions from source via AST and exec.
    Reasoning

    The docs config parses the package source with ast and execs only a selected _format_version function and version assignments to read the version without importing the package. This is a known build-time pattern, and the code is local and readable.

  5. info critical → info by review dynamic-execution docs/conf.py:55:14

    `compile` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

        if isinstance(node, ast.FunctionDef) and node.name == "_format_version":
            exec(compile(ast.Module(body=[node], type_ignores=[]), "<v>", "exec"), _ns)
        elif isinstance(node, ast.Assign) and any(
            getattr(t, "id", None) in ("__version_info__", "__version__")
    likely benign LLM, confidence 0.85 compile of an AST module built from the project's own source in docs config.
    Reasoning

    The compile call is part of the same AST-extraction routine that feeds exec, operating on parsed source nodes from the project's own file. It is a legitimate version-reading technique.

  6. info critical → info by review dynamic-execution docs/conf.py:60:9

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

        ):
            exec(compile(ast.Module(body=[node], type_ignores=[]), "<v>", "exec"), _ns)
    
    version_info = _ns["__version_info__"]
    likely benign LLM, confidence 0.85 Docs config exec of extracted version nodes into a local namespace.
    Reasoning

    The exec re-runs the selected AST nodes into a namespace to obtain __version_info__. The input is the repository's own source, not external data.

  7. info critical → info by review dynamic-execution docs/conf.py:60:14

    `compile` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

        ):
            exec(compile(ast.Module(body=[node], type_ignores=[]), "<v>", "exec"), _ns)
    
    version_info = _ns["__version_info__"]
    likely benign LLM, confidence 0.85 compile of extracted version AST nodes in docs config.
    Reasoning

    Same AST-based version extraction as the neighboring exec; the compiled input comes from the package's own source.

  8. info warn → info by review dynamic-attribute src/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 through vars() in wrapt's patching helper.
    Reasoning

    wrapt is a decorator and wrapping library, and this vars() lookup resolves attributes through the MRO when patching. Name-based attribute access is inherent to the library's purpose.

  9. info warn → info by review dynamic-attribute src/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 Retrieves the prior attribute value via vars() before wrapping it.
    Reasoning

    vars(parent).get is used to fetch the prior attribute so a wrapper can be applied and later restored. This is standard monkey-patch bookkeeping in a wrapping library.

  10. info warn → info by review dynamic-attribute src/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 MRO traversal using vars() to locate an attribute's original definition.
    Reasoning

    The MRO walk over vars(cls) finds the original descriptor for an attribute, which is legitimate introspection needed to wrap methods correctly.

  11. info critical → info by review dynamic-import src/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 Lazy import helper in the object proxy module.
    Reasoning

    This is the lazy-import helper for wrapt's lazy object proxy, importing a module named by the caller using fromlist. It is ordinary library behavior and the name is not attacker-controlled input.

  12. info critical → info by review dynamic-execution tests/core/test_adapter.py:18:1

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

    decorators = types.ModuleType("decorators")
    exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__)
    likely benign LLM, confidence 0.85 Test fixture that execs a local code string into a fresh module.
    Reasoning

    The test builds a module from a DECORATORS_CODE string constant defined in the test file itself. This is fixture setup for adapter tests, not hidden execution.

  13. info critical → info by review dynamic-execution tests/core/test_adapter_annotations.py:26:1

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

    decorators = types.ModuleType("decorators")
    exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__)
    likely benign LLM, confidence 0.85 Test fixture exec of a local decorator code string.
    Reasoning

    Same test fixture pattern: a locally defined string is exec'd into a ModuleType for annotation tests.

  14. info critical → info by review dynamic-execution tests/core/test_adapter_kwonly.py:18:1

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

    decorators = types.ModuleType("decorators")
    exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__)
    likely benign LLM, confidence 0.85 Test fixture exec of a local decorator code string for kwonly tests.
    Reasoning

    Test fixture execs a constant string defined in the same file to build decorators for keyword-only argument tests.

  15. info critical → info by review dynamic-execution tests/core/test_class.py:16:1

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

    decorators = types.ModuleType("decorators")
    exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__)
    likely benign LLM, confidence 0.85 Test fixture exec of a local decorator code string for class tests.
    Reasoning

    The class test fixture execs a locally defined code string into a module namespace. This is standard test scaffolding.

  16. info critical → info by review dynamic-import tests/core/test_find_wrapper.py:90:27

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

    
            wrapt.apply_patch(__import__(__name__), "function_closure", their_closure)
    
            current = wrapt.resolve_path(__name__, "function_closure")[2]
    likely benign LLM, confidence 0.92 Test calls __import__ on the module's own __name__ to obtain it for wrapt patching.
    Reasoning

    `__import__(__name__)` imports the current module by its own name, a common idiom in test code to get a module object for patching. The file is a wrapt test for patching and path resolution. Nothing here hides code or reaches outside the test.

  17. info critical → info by review dynamic-import tests/core/test_find_wrapper.py:219:27

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

    
            wrapt.apply_patch(__import__(__name__), "function_replaced", original)
    
            current = wrapt.resolve_path(__name__, "function_replaced")[2]
    likely benign LLM, confidence 0.92 Test uses __import__(__name__) to fetch its own module for a wrapt patching test.
    Reasoning

    Same pattern as the sibling finding: `__import__(__name__)` retrieves the current module inside a wrapt test that patches a function and resolves its path. The argument is the module's own name, not attacker-controlled input.

  18. info critical → info by review dynamic-execution tests/core/test_function.py:16:1

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

    decorators = types.ModuleType("decorators")
    exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__)
    likely benign LLM, confidence 0.85 Test module execs a locally defined decorator-source string into a fresh ModuleType namespace.
    Reasoning

    This is a wrapt test fixture. The exec runs DECORATORS_CODE, a source string defined in the project's own test suite, into a module namespace created for the test. It is a standard way to build decorator fixtures, and the snippet shows no network, file, or shell activity. The finding is flagged only because the argument is a name rather than a literal.

  19. info critical → info by review dynamic-execution tests/core/test_inner_classmethod.py:16:1

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

    decorators = types.ModuleType("decorators")
    exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__)
    likely benign LLM, confidence 0.85 Test execs an in-repo decorators code string into a test module namespace.
    Reasoning

    Same fixture pattern as other wrapt tests: exec of a project-defined DECORATORS_CODE string into a ModuleType's dict to construct decorators for testing. No evidence of external input or malicious behavior in the snippet.

  20. info critical → info by review dynamic-execution tests/core/test_inner_staticmethod.py:16:1

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

    decorators = types.ModuleType("decorators")
    exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__)
    likely benign LLM, confidence 0.85 Test execs an in-repo decorators code constant into a test module namespace.
    Reasoning

    Standard wrapt test fixture: exec of the in-repo DECORATORS_CODE constant into a ModuleType namespace. The snippet shows no sign of obfuscation or external payload.

  21. info critical → info by review dynamic-execution tests/core/test_instancemethod.py:16:1

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

    decorators = types.ModuleType("decorators")
    exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__)
    likely benign LLM, confidence 0.85 Test execs an in-repo decorators source string to build fixtures for instancemethod tests.
    Reasoning

    Repeated wrapt test fixture pattern: exec of the project's DECORATORS_CODE string into a generated module's dict. This is test scaffolding, not a dropper or hidden logic.

  22. info critical → info by review dynamic-execution tests/core/test_nested_function.py:16:1

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

    decorators = types.ModuleType("decorators")
    exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__)
    likely benign LLM, confidence 0.85 Test execs in-repo decorator source into a module namespace for nested-function tests.
    Reasoning

    Identical fixture construction: exec of the in-repo DECORATORS_CODE constant into a ModuleType namespace for nested-function tests. No external input or suspicious behavior is visible.

  23. info critical → info by review dynamic-execution tests/core/test_object_proxy.py:23:1

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

    objects = types.ModuleType("objects")
    exec(OBJECTS_CODE, objects.__dict__, objects.__dict__)
    likely benign LLM, confidence 0.85 Test execs an in-repo OBJECTS_CODE constant into a test module namespace for object-proxy tests.
    Reasoning

    Test fixture that execs the project's OBJECTS_CODE string into a ModuleType namespace to create proxy test objects. The pattern is standard for wrapt's test suite and the snippet shows no malicious activity.

  24. info critical → info by review dynamic-execution tests/core/test_outer_classmethod.py:18:1

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

    decorators = types.ModuleType("decorators")
    exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__)
    likely benign LLM, confidence 0.85 Test execs an in-repo decorators code string for outer-classmethod test setup.
    Reasoning

    Same wrapt fixture pattern: exec of the local DECORATORS_CODE constant into a ModuleType dict. It is test scaffolding and shows no sign of encoded or hidden payloads.

  25. info critical → info by review dynamic-execution tests/core/test_outer_staticmethod.py:16:1

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

    decorators = types.ModuleType("decorators")
    exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__)
    likely benign LLM, confidence 0.85 Test execs an in-repo decorators source string for outer-staticmethod test setup.
    Reasoning

    Standard test fixture: exec of the project's DECORATORS_CODE into a generated module namespace. The snippet gives no indication of external or malicious code.

  26. info critical → info by review dynamic-execution tests/core/test_type_module_attribute.py:31:1

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

    objects = types.ModuleType("objects")
    exec(OBJECTS_CODE, objects.__dict__, objects.__dict__)
    likely benign LLM, confidence 0.85 Test execs an in-repo OBJECTS_CODE string into a module namespace for type/module attribute tests.
    Reasoning

    Test fixture execing the local OBJECTS_CODE constant into a ModuleType namespace, consistent with the rest of wrapt's test suite. No evidence of obfuscation or malicious intent.

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/GrahamDumpleton/wrapt wrapt && cd wrapt
git checkout 2.5.2rc1
disclude scan --severity info --diff 2.5.1 .