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.