macOS Keychain for developers: storing API keys safely

Apple’s Keychain is one of the most under-used building blocks in a Mac developer’s security stack. It is not magic — it is an OS-managed secret store with APIs that apps use to persist passwords, certificates, and tokens with access controls that plaintext .env files do not provide.

This article explains what Keychain gives you, where it does not help, and how developer-focused tools (including PassStore) build on it.


1. What Keychain Services actually does

Apple documents Keychain Services as a way to store small pieces of sensitive data — passwords, keys, tokens — outside your app’s casual reach, with integration into system authentication (password, Touch ID, Apple Watch, etc.) depending on item configuration.

Developer documentation (Apple):
Keychain Services

Conceptually:

  • Data is stored in encrypted databases managed by the OS.
  • Apps request access via APIs (Security framework) with attributes describing who can read the item.
  • Users can inspect and delete items in Keychain Access.app (useful when debugging “where did that old token go?”).

2. Keychain vs .env files (honest comparison)

Dimension.env on diskKeychain-backed storage
At-rest exposurePlaintext in your project tree (unless extra encryption)OS-managed encryption; not a normal document file
Accidental sharingEasy to zip, sync, or commitNot included in casual “here is my repo folder” exports
Copy/paste ergonomicsTrivial (cat .env)Requires app support or security CLI for ad-hoc workflows
CI serversCommon (not Keychain)Usually wrong tool — use CI secret storage
Cross-platformWorks everywheremacOS / Apple ecosystem native

Takeaway: Keychain is a strong default for developer secrets on a Mac. It is not a replacement for cloud secret managers in production multi-tenant environments.


3. When developers should still use environment variables

Environment variables remain the lingua franca of:

  • Local servers (PORT, NODE_ENV).
  • Container orchestration (docker run -e).
  • Many language runtimes loading config at process start.

The goal is not to eliminate process.env. The goal is to avoid long-lived plaintext files as the canonical store for high-value secrets on laptops.

Pattern: vault → explicit copy → shell session or tool config for the duration of work.


4. Ad-hoc CLI: reading and writing Keychain items (careful)

Apple ships the security command. Examples below are educational — prefer a dedicated app for day-to-day workflow.

Add a generic password (interactive)

security add-generic-password \
  -a "myapp-dev" \
  -s "STRIPE_SECRET_KEY" \
  -w "sk_test_...."

Retrieve (prints secret to stdout — mind shoulder surfing / logs)

security find-generic-password -a "myapp-dev" -s "STRIPE_SECRET_KEY" -w

Risks:

  • Scripts that echo secrets into logs.
  • Items created without thinking through access groups and visibility.

For most developers, a GUI vault with Keychain integration is easier to audit than one-off shell scripts.


5. Threat model reminders

PassStore’s Security overview states the high-level model plainly: no desktop app can promise safety if malware controls your unlocked session or your master password is compromised. Keychain raises the bar for casual file theft and accidental distribution; it does not replace disk encryption (FileVault), screen locks, or phishing awareness.


6. How PassStore uses Keychain (summary)

PassStore is a native macOS vault for developer-oriented secrets. Sensitive values can be stored using Keychain Services, while the vault file itself is encrypted at rest with modern algorithms (see /security for AES-GCM, Argon2id, and migration notes).

Typical wins:

  • One organized place for API keys and credential bundles.
  • Less temptation to keep “just in case” .env copies on disk.
  • Alignment with Apple platform conventions you already trust for Wi‑Fi passwords and certificates.

Download PassStore.


7. Related guides