[security] api_key_manager.py stores encryption key in plaintext .key file with no file permissions #706

Closed
opened 2026-06-02 23:56:44 +02:00 by sleepy · 0 comments
Owner

File: src/api_key_manager.py

Problems:

  1. No file permissions on the encryption key file (line 19): The .key file containing the Fernet encryption key is written with default permissions. No os.chmod(path, 0o600) or safe_chmod() call. Any user on the system can read the encryption key, making the encryption worthless.

  2. No integrity verification (line 14): The key file is read blindly with no length/format validation. A truncated or corrupted key file silently produces a Fernet instance that can't decrypt existing data.

  3. Plaintext encryption key at rest: The Fernet key itself is stored as raw bytes in .key. Compare with integrations.py which uses core.atomic_io and safe_chmod for its data file. The key file should have the same protection.

  4. load() decrypts all keys on every call (lines 44–53): load() decrypts every stored API key and returns them as a dict. Callers get plaintext keys in memory. No access logging or audit trail.

Fix:

  • Call safe_chmod(key_file, 0o600) after writing the key
  • Validate key file size/content before use
  • Consider using the project's existing secret_storage module instead of a standalone Fernet instance
**File:** `src/api_key_manager.py` **Problems:** 1. **No file permissions on the encryption key file** (line 19): The `.key` file containing the Fernet encryption key is written with default permissions. No `os.chmod(path, 0o600)` or `safe_chmod()` call. Any user on the system can read the encryption key, making the encryption worthless. 2. **No integrity verification** (line 14): The key file is read blindly with no length/format validation. A truncated or corrupted key file silently produces a Fernet instance that can't decrypt existing data. 3. **Plaintext encryption key at rest**: The Fernet key itself is stored as raw bytes in `.key`. Compare with `integrations.py` which uses `core.atomic_io` and `safe_chmod` for its data file. The key file should have the same protection. 4. **`load()` decrypts all keys on every call** (lines 44–53): `load()` decrypts every stored API key and returns them as a dict. Callers get plaintext keys in memory. No access logging or audit trail. **Fix:** - Call `safe_chmod(key_file, 0o600)` after writing the key - Validate key file size/content before use - Consider using the project's existing `secret_storage` module instead of a standalone Fernet instance
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sleepy/odysseus#706
No description provided.