PyPI / werkzeug / 3.1.9

werkzeug 3.1.9

Source
https://github.com/pallets/werkzeug
Artifact scanned
werkzeug-3.1.9-py3-none-any.whl (wheel · 223.3 KB · SHA-256 6392e50c7846…)
Compared with
werkzeug-3.1.8-py3-none-any.whl (0 signals introduced since)
Files
55 scanned, 8 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 6 info
Scan time
7.2 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 6 of 6 warn and critical signals; 6 demoted to info.
Disclude version
4.3.0
Scanned (UTC)
2026-10-23 06:49

Signals

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

  1. info warn → info by review dynamic-execution werkzeug/debug/console.py:177:13

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

            try:
                exec(code, self.locals)
            except Exception:
                self.showtraceback()
    likely benign LLM, confidence 0.90 Werkzeug's debugger console executes user-entered Python code in its REPL.
    Reasoning

    This is the exec inside the Werkzeug interactive debugger console, which evaluates code a developer types into the debugger REPL. Running arbitrary code is the feature. The snippet is an ordinary try/except around exec with no decoding or hidden payload. It is only a risk if the debugger is exposed, which is a deployment issue rather than an obfuscation signal.

  2. info warn → info by review frame-introspection werkzeug/debug/repr.py:49:30

    `sys._getframe` — call-stack frame introspection (ast pass, confidence 0.70)

        if obj is missing:
            rv = gen.dump_locals(sys._getframe(1).f_locals)
        else:
            rv = gen.dump_object(obj)
    likely benign LLM, confidence 0.88 Werkzeug's debug repr helper reads the caller's frame locals to render them in the debugger.
    Reasoning

    sys._getframe(1).f_locals is used by the debugger's dump_locals helper to display the caller's local variables in the debug UI. This is a standard introspection technique for a debugging library and shows no exfiltration or hidden behaviour in the snippet.

  3. info warn → info by review dynamic-execution werkzeug/routing/rules.py:736:9

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

            locs: dict[str, t.Any] = {}
            exec(code, globs, locs)
            return locs[name]  # type: ignore
    likely benign LLM, confidence 0.88 Werkzeug's routing code generator execs internally compiled code to build a rule function.
    Reasoning

    This exec runs a code object built by Werkzeug's routing rules compiler, which generates a matcher/builder function from its own AST. The name is looked up in locs and returned. The code is produced internally by the library rather than from an external or encoded source, so this is a legitimate code-generation pattern.

  4. info warn → info by review dynamic-execution werkzeug/routing/rules.py:836:16

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

    
            code = compile(module, "<werkzeug routing>", "exec")
            return self._get_func_code(code, func_ast.name)
    likely benign LLM, confidence 0.88 Werkzeug's routing generator compiles its own generated module AST into a code object.
    Reasoning

    compile() is applied to a module AST built by Werkzeug's own routing generator, with a fixed filename '<werkzeug routing>'. The result feeds the same internal codegen path. It is a legitimate use of compile for generated code, not a sign of an encoded dropper.

  5. info critical → info by review dynamic-import werkzeug/utils.py:589:13

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

            try:
                __import__(import_name)
            except ImportError:
                if "." not in import_name:
    likely benign LLM, confidence 0.93 Werkzeug's import_string helper dynamically imports a module by name.
    Reasoning

    This is werkzeug.utils.import_string, a documented helper that imports a module by dotted name supplied by the developer, such as in configuration strings. The __import__ call on a variable is its intended purpose. The critical severity is an overrating of a normal dynamic import in a library, not evidence of malice.

  6. info critical → info by review dynamic-import werkzeug/utils.py:597:18

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

            module_name, obj_name = import_name.rsplit(".", 1)
            module = __import__(module_name, globals(), locals(), [obj_name])
            try:
                return getattr(module, obj_name)
    likely benign LLM, confidence 0.93 Werkzeug's import_string resolves a dotted 'module.attr' path via __import__ and getattr.
    Reasoning

    The snippet shows import_string splitting a dotted path and calling __import__(module_name, ..., [obj_name]) to fetch an attribute, a standard pattern used to resolve 'module.object' references. It is not obfuscated and has no network or decoding component.

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 werkzeug-3.1.9-py3-none-any.whl https://files.pythonhosted.org/packages/a1/38/df03f564f43cec2684823f3cccae1a652ee7face1cbaa76fb223096e64d7/werkzeug-3.1.9-py3-none-any.whl
printf '%s  %s\n' 6392e50c78460ba618e5b21f08a71f59c99ce99cdc6cf6e3dd7e6ccca8754fab werkzeug-3.1.9-py3-none-any.whl | shasum -a 256 -c -
unzip -q werkzeug-3.1.9-py3-none-any.whl -d pkg
disclude scan --untrusted --severity info pkg