Skip to content

security: Replace plaintext API key storage with OS keychain via keyring #37

Description

@Lyellr88

Current State

When MARM_API_KEY is set, the dashboard saves it to ~/.marm/.env as plaintext so it persists across restarts without requiring the env var on every session. The dashboard and MCP server both read from this file on startup.

Risk

Low on a personal single-user machine - the file sits in the user profile, which has OS-level ACL protection.

Higher on shared or remote machines - any user or process with filesystem access can read the key in plaintext. This becomes a real concern for anyone running MARM on a VPS, homelab server, or shared dev environment.

Proposed Fix

Replace (or augment) the flat .env file with OS keychain storage using the keyring Python package.

keyring abstracts across all three major platforms with a single API:

  • Windows - Credential Manager
  • macOS - Keychain
  • Linux - Secret Service (GNOME Keyring / KWallet)
import keyring

# Store
keyring.set_password("marm-mcp", "api-key", api_key_value)

# Retrieve
api_key = keyring.get_password("marm-mcp", "api-key")

Scope

  • Add keyring as an optional or required dependency in pyproject.toml
  • On API key save: write to keychain instead of (or alongside) ~/.marm/.env
  • On server/dashboard startup: attempt keychain read first, fall back to .env for backward compatibility
  • Graceful fallback if keychain is unavailable (e.g., headless Linux without a Secret Service daemon)

Cross-Platform Considerations

  • Linux headless environments may not have a Secret Service daemon running; keyring will raise NoKeyringError. A fallback to the existing .env behavior keeps compatibility.
  • Docker containers: keychain won't be available; .env file or env var injection remains the path there.
  • The fallback chain should be: keychain → ~/.marm/.envMARM_API_KEY env var

Files to Look At

  • Dashboard API key save logic
  • marm_mcp_server/core/settings.py - startup key resolution
  • pyproject.toml - dependency addition

Notes

The keyring package is well-maintained and widely used (pip, Poetry, AWS CLI all use it). The main implementation challenge is the graceful fallback for environments where no keychain backend is available.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions