PyPI / cyclopts / 5.3.0

cyclopts 5.3.0

Source
https://github.com/BrianPugh/cyclopts
Artifact scanned
cyclopts-5.3.0-py3-none-any.whl (wheel · 289.7 KB · SHA-256 479f92942ea2…)
Compared with
cyclopts-5.2.0-py3-none-any.whl (0 signals introduced since)
Files
81 scanned, 5 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 5 info
Scan time
5.5 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 5 of 5 warn and critical signals; 5 demoted to info.
Disclude version
4.3.0
Scanned (UTC)
2026-10-23 15:12

Signals

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

  1. info warn → info by review dynamic-attribute cyclopts/__init__.py:107:13

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

                module = importlib.import_module(module_path)
                globals()[name] = module
                return module
            else:
    likely benign LLM, confidence 0.93 Lazy-loading __getattr__ in the cyclopts package that imports a submodule and caches it in globals().
    Reasoning

    This is the standard PEP 562 module-level __getattr__ pattern for lazy submodule loading: it imports a named submodule with importlib and caches it in globals(). It is a common, legitimate way to reduce import cost in a library package, and the snippet contains no decoding, network access, or process spawning.

  2. info warn → info by review dynamic-attribute cyclopts/__init__.py:113:13

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

                value = getattr(module, name)
                globals()[name] = value
                return value
        raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
    likely benign LLM, confidence 0.93 Module __getattr__ that resolves a name from a lazily imported module and caches it, otherwise raising AttributeError.
    Reasoning

    Same PEP 562 lazy-attribute pattern: getattr on an already-imported module, cached in globals, then AttributeError raised for unknown names. This is ordinary package plumbing with no obfuscation or malicious behaviour.

  3. info critical → info by review frame-introspection cyclopts/core.py:121:17

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

        """Get the calling package name from the call-stack."""
        for elem in inspect.stack():
            module = inspect.getmodule(elem.frame)
            if module is None:
    likely benign LLM, confidence 0.90 Call-stack walk via inspect.stack() to determine the name of the calling package for the CLI app.
    Reasoning

    Walking inspect.stack() to find the calling module's name is a known way for CLI frameworks to infer the default app name. The 'anti-analysis shape' note only comes from sys.exit/exec/eval appearing elsewhere in the file, which is normal for a CLI library that exits on error and evaluates nothing suspicious here. The critical severity is an over-flag.

  4. info critical → info by review frame-introspection cyclopts/core.py:592:21

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

            try:
                frame = sys._getframe(2)
                self._instantiating_module_name = frame.f_globals.get("__name__")
            except (IndexError, AttributeError):
    likely benign LLM, confidence 0.90 Reads the caller's module name via sys._getframe to record which module instantiated the App.
    Reasoning

    sys._getframe(2) read only to take f_globals['__name__'] of the instantiating module, wrapped in an IndexError/AttributeError guard. This is a benign introspection idiom for recording where an App was created. It does not evade analysis or execute anything.

  5. info critical → info by review frame-introspection cyclopts/core.py:3341:17

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

    
        for elem in inspect.stack():
            frame = elem.frame
            f_back = frame.f_back
    likely benign LLM, confidence 0.90 Iterates the call stack and walks f_back frames to locate the calling context.
    Reasoning

    Iterating inspect.stack() and walking f_back to locate a calling frame, the same benign calling-context discovery as the other frame-introspection findings in this library. Nothing in the snippet is executed, decoded, or sent over the network.

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 cyclopts-5.3.0-py3-none-any.whl https://files.pythonhosted.org/packages/e7/99/00ce1a4e8b131b0e0a59a882311bcb9f771e7e39004bd19d988f1dddf303/cyclopts-5.3.0-py3-none-any.whl
printf '%s  %s\n' 479f92942ea286b6c132f64262d82f12b4c71d003f3d3691f572cd6ad4528bb2 cyclopts-5.3.0-py3-none-any.whl | shasum -a 256 -c -
unzip -q cyclopts-5.3.0-py3-none-any.whl -d pkg
disclude scan --untrusted --severity info pkg