Storing Secrets in macOS Keychain

February 6, 2026

I ran into a problem yesterday: I needed my 1Password service account token available in my shell, but I didn't want it hardcoded in .zshrc where anyone with file access could read it.

The solution: store it in macOS Keychain.

Storing the secret

security add-generic-password \
  -a "$USER" \
  -s "MY_SECRET_TOKEN" \
  -w "your-actual-token-here" \
  -U

The -U flag updates if it already exists. The -s is the service name (how you'll look it up later).

The gotcha: hex encoding

When you retrieve it, Keychain returns hex-encoded bytes, not the original string:

security find-generic-password -a "$USER" -s "MY_SECRET_TOKEN" -w
# Returns something like: 6f702d73612d...

You need to decode it:

security find-generic-password -a "$USER" -s "MY_SECRET_TOKEN" -w | xxd -r -p

Putting it in your shell

Add this to .zshrc:

export MY_SECRET_TOKEN=$(security find-generic-password \
  -a "$USER" \
  -s "MY_SECRET_TOKEN" \
  -w 2>/dev/null | xxd -r -p | tr -d ' \r\n')

The tr -d ' \r\n' strips any whitespace that might have snuck in.

After reboot

If the Keychain is locked (common after reboot), you'll need to unlock it first:

security unlock-keychain ~/Library/Keychains/login.keychain-db

Then your exports will work.

Why bother?

  • Secrets aren't in plaintext files
  • Works with any tool that reads environment variables
  • Keychain is encrypted at rest
  • You can use the same pattern for multiple tokens

Small thing, but it's the difference between credentials that could leak and credentials that stay locked down.

Get new posts via email

New posts delivered to your inbox. No spam.