PyPI / keyring / 25.7.0

keyring 25.7.0

Source
https://github.com/jaraco/keyring
Artifact scanned
keyring-25.7.0-py3-none-any.whl (wheel · 38.2 KB · SHA-256 be4a0b195f14…)
Compared with
keyring-25.6.0-py3-none-any.whl (0 signals introduced since)
Files
32 scanned, 5 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 7 info
Scan time
6.3 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 09:06

Signals

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

  1. info warn → info by review dynamic-execution keyring/backend_complete.bash:8:3

    command name is a variable () not set in this file — the caller or environment decides what runs (ast pass, confidence 0.70)

    	choices=$(
    		"${COMP_WORDS[0]}" --list-backends 2>/dev/null |
    			while IFS=$' \t' read -r backend rest; do
    				printf "%s\n" "$backend"
    likely benign LLM, confidence 0.90 Bash tab-completion helper that invokes the keyring command itself with --list-backends to gather backend names.
    Reasoning

    The variable command is COMP_WORDS[0], the keyring program the user is completing. Calling it with --list-backends to list choices is the standard way a bash completion script works. It runs the tool being completed, not an attacker-chosen command.

  2. info warn → info by review dynamic-execution keyring/backend_complete.zsh:12:14

    command name is a variable (`$words`) not set in this file — the caller or environment decides what runs (ast pass, confidence 0.70)

    		choices+=(${${line/ \(priority: /\\\\:}/)/})
    	done <<< "$($words[1] --list-backends)"
    	_arguments "*:keyring priority:(($choices))"
    }
    likely benign LLM, confidence 0.90 Zsh completion function that runs the keyring command with --list-backends to offer priority choices.
    Reasoning

    $words[1] is the command the user typed in the zsh completion context, here the keyring program. Running it with --list-backends is the expected completion behaviour, the same as the bash variant.

  3. info critical → info by review dynamic-import keyring/core.py:134:5

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

        module_name, sep, class_name = keyring_name.rpartition('.')
        __import__(module_name)
        module = sys.modules[module_name]
        return getattr(module, class_name)
    likely benign LLM, confidence 0.85 Loads a keyring backend class by dotted name using __import__ and getattr.
    Reasoning

    The module name comes from splitting a configured backend name on its last dot, and the code then looks up the class with getattr. This is the plugin loading mechanism for keyring backends. The critical severity overstates it, since loading a configured module is the documented purpose and the snippet shows no decoding or fetching of remote code.

  4. info unicode-homoglyph keyring/testing/backend.py:19:6

    identifier `ξεσκεπάζωτηνψυχοφθόραβδελυγμία` contains homoglyph candidates: κ (03BA)→k, η (03B7)→n, ν (03BD)→v, ο (03BF)→o (in string/comment) (raw pass, confidence 0.35)

        "זהכיףסתםלשמועאיךתנצחקרפדעץטובבגן"
        "ξεσκεπάζωτηνψυχοφθόραβδελυγμία"
        "Съешьжеещёэтихмягкихфранцузскихбулокдавыпейчаю"
  5. info unicode-mixed-script keyring/testing/backend.py:19:6

    identifier `ξεσκεπάζωτηνψυχοφθόραβδελυγμία` mixes scripts: Greek + Latin (in string/comment) (raw pass, confidence 0.40)

        "זהכיףסתםלשמועאיךתנצחקרפדעץטובבגן"
        "ξεσκεπάζωτηνψυχοφθόραβδελυγμία"
        "Съешьжеещёэтихмягкихфранцузскихбулокдавыпейчаю"
  6. info warn → info by review dynamic-attribute keyring/util/platform_.py:39:13

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

    # by default, use Unix convention
    data_root = globals().get('_data_root_' + platform.system(), _data_root_Linux)
    config_root = globals().get('_config_root_' + platform.system(), _config_root_Linux)
    likely benign LLM, confidence 0.92 Selects the data root path constant for the current OS by building a name and reading it from globals().
    Reasoning

    The lookup key is a fixed prefix plus platform.system(), which returns a small set of OS names. The fallback is the Linux default. It only selects one of several predefined path constants in the same module and performs no execution or network access.

  7. info warn → info by review dynamic-attribute keyring/util/platform_.py:40:15

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

    data_root = globals().get('_data_root_' + platform.system(), _data_root_Linux)
    config_root = globals().get('_config_root_' + platform.system(), _config_root_Linux)
    likely benign LLM, confidence 0.92 Selects the config root path constant for the current OS by name lookup in module globals.
    Reasoning

    This is the same platform-keyed globals lookup as the preceding line, this time for the config root. Its key is a fixed prefix plus the OS name, and the result is only a path constant, so the risk is negligible.

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 keyring-25.7.0-py3-none-any.whl https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl
printf '%s  %s\n' be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f keyring-25.7.0-py3-none-any.whl | shasum -a 256 -c -
unzip -q keyring-25.7.0-py3-none-any.whl -d pkg
disclude scan --untrusted --severity info pkg