diff --git a/src/api_key_manager.py b/src/api_key_manager.py index 650a1fbf7..f0d25ced6 100644 --- a/src/api_key_manager.py +++ b/src/api_key_manager.py @@ -57,7 +57,12 @@ class APIKeyManager: # Legacy/wrong shape (e.g. a list) — .items() would raise. Ignore it. logger.warning("API keys file has unexpected shape (%s); ignoring", type(encrypted_keys).__name__) return {} - return encrypted_keys + + return { + str(provider): key + for provider, key in encrypted_keys.items() + if isinstance(key, str) + } def save(self, provider: str, api_key: str): """Save encrypted API key to file. @@ -82,4 +87,3 @@ class APIKeyManager: except (InvalidToken, ValueError) as e: logger.warning("Failed to decrypt API key for %s: %s", provider, e) return decrypted - diff --git a/tests/test_api_key_manager_resilience.py b/tests/test_api_key_manager_resilience.py index 8654a6984..a209b0a29 100644 --- a/tests/test_api_key_manager_resilience.py +++ b/tests/test_api_key_manager_resilience.py @@ -33,3 +33,19 @@ def test_api_key_manager_load_resilience(tmp_path): assert loaded["good_provider"] == "good_value" assert "bad_provider" not in loaded assert "garbage_provider" not in loaded + + +def test_load_ignores_non_string_raw_values(tmp_path): + mgr = APIKeyManager(str(tmp_path)) + + mgr.save("openai", "sk-openai") + with open(mgr.api_keys_file, "r", encoding="utf-8") as f: + keys = json.load(f) + + keys["missing_provider"] = None + keys["numeric_provider"] = 42 + keys["object_provider"] = {"encrypted": keys["openai"]} + with open(mgr.api_keys_file, "w", encoding="utf-8") as f: + json.dump(keys, f) + + assert mgr.load() == {"openai": "sk-openai"}