Safeguard
Developer Tools•

Where should a CLI store its API token: keychain or a file?

Prefer the operating system's secure store over a plain file. Git's own credential helpers show the trade-offs between cache, store and keychain.

Safeguard Security Team
4 min read

Prefer the operating system's secure credential store, such as the macOS keychain, and fall back to a file only when none exists. Git's documentation is a handy reference: its store helper writes credentials to disk in plaintext, while other helpers talk to the system keychain.

The three options Git already documents

Git needs the same thing your CLI does, a secret that survives between runs. Its manual describes three approaches.

ApproachWhere the secret livesLifetime
cache helperIn memoryShort period, then gone
store helperA file on diskIndefinitely
OS-backed helperSystem keychain or walletUntil removed

The Git credentials manual describes cache as caching credentials in memory for a short period, and store as storing credentials indefinitely on disk. It lists helpers with secure persistent storage for each platform, including libsecret on Linux, osxkeychain on macOS and wincred on Windows, plus Git Credential Manager as a cross-platform option.

The git-credential-store page is blunt about the file: it is stored in plaintext, one credential per line as a URL with the user and password in it.

Why a plaintext file is risky for a developer tool

A token in a home directory file can be read by any process running as that user. That includes a malicious package install script, a compromised editor extension, and a backup tool. It can also be swept into a dotfiles repository by accident, or into a container image if someone copies the home directory.

Developer machines run a lot of third-party code. A keychain adds a layer, because access is brokered by the operating system and often needs user approval.

A practical order of preference

  1. OAuth or device login with short-lived tokens. Git's manual also describes OAuth helpers as an alternative to typing passwords or personal access tokens, with background authentication after the first sign in. Short-lived credentials limit what a stolen file is worth.
  2. System keychain. Store the refresh or long-lived token here.
  3. In-memory only. For one-off runs, ask for the secret and keep it for the process.
  4. A file, last. If you must, create it with owner-only permissions, keep it outside any directory people commit, and say so in your docs.

Steps to implement

  1. Choose a keychain library for each platform you ship to, or call the platform tool.
  2. Store one entry per account and host, not one global secret.
  3. Add a logout command that deletes the entry.
  4. When you fall back to a file, print a notice once, naming the path.
  5. Support an environment variable for CI, but document that it is for unattended runs.
  6. Never print the token in logs, including debug logs.

Do not forget revocation

Give users a way to see which tokens exist and to revoke them from the server side. A stolen token you cannot revoke is a long incident.

Quick check

Is the Git store helper encrypted?

No. The Git documentation says the credentials file is stored in plaintext, so treat it as readable by anything running as that user.

Is an environment variable safer than a file?

It avoids a file at rest, but other processes of the same user may be able to read it. Use it for CI runs and prefer a keychain on laptops.

Safeguard's free scan at gold.safeguard.sh/scan can show which third-party packages your CLI ships, since those run with the same access as your token store.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.