[MODEL] Claude advises storing users' secrets in the macOS keychain with "security add-generic-password" — the secret enters the transcript and every later session can read it without a prompt
Preflight Checklist
- [x] I have searched existing issues for similar behavior reports
- [x] This report does NOT contain sensitive information (API keys, passwords, etc.)
Type of Behavior Issue
Other unexpected behavior
What You Asked Claude to Do
My script needs an API token for a service. How do I store it securely on my Mac so the script can use it?
What Claude Actually Did
Recommended the macOS keychain and proposed storing the token with:
security add-generic-password -a "$USER" -s "my-service-token" -w "<token>"
Offered to run that command itself through the Bash tool, with the real token value as the -w argument.
For the script, and for checking that the item exists, proposed reading it back with security find-generic-password -s "my-service-token" -w, and offered to run that too.
Presented this as the secure option. It did not mention either consequence below.
Consequences the user is not told about:
The secret enters the session. Passed as an argument to a command the agent runs, the value is in the conversation context and in the session transcript on disk, where it stays after the task is over.
Every later session can read it back silently. A keychain item created by /usr/bin/security lists security among the applications trusted to read it. From then on security find-generic-password -w returns the secret with no system prompt — in any future session, on any task, including one that is processing untrusted content. The user believes the keychain protects the secret, while the one consumer the keychain's prompt would have stopped — the agent — has standing, silent access.
Expected Behavior
Claude does not put a user's secret on a command line it runs.
When recommending the keychain, Claude tells the user to add the item themselves — through Keychain Access, or with an interactive command the user runs in their own terminal so the value is typed at a prompt rather than passed as an argument.
Claude states the trade-off: an item created by security is readable by security without a prompt, which includes every future agent session.
Files Affected
Permission Mode
Accept Edits was OFF (manual approval required)
Can You Reproduce This?
Sometimes (intermittent)
Steps to Reproduce
In a fresh session, ask the prompt above. Claude typically proposes security add-generic-password ... -w "<token>" and offers to run it.
Create an item with a dummy value the same way:
security add-generic-password -a probe -s probe-service -w dummy-secret-123
Start a new session and ask Claude to run:
security find-generic-password -s probe-service -w
dummy-secret-123 is printed into the session. No system prompt appears.
Contrast: delete the item, add one with the same service and account through Keychain Access (File > New Password Item), and run the same read. macOS now asks whether security may use the confidential information stored in the item.
Clean up:
security delete-generic-password -s probe-service
Claude Model
Opus
Relevant Conversation
Claude: The most secure option on macOS is the system keychain. I can store
the token there for you:
security add-generic-password -a "$USER" -s "my-service-token" -w "<token>"
and your script can then read it with
security find-generic-password -s "my-service-token" -w
Impact
High - Significant unwanted changes
Claude Code Version
2.1.299 (Claude Code)
Platform
Anthropic API
Additional Context
The dropdowns above don't cover this kind of impact: nothing was modified or lost. What happens is that a credential is exposed twice — once into the transcript at the moment it is stored, and then permanently, as a silent read path for every session that follows.
What this is not. Not a keychain bug: macOS behaves as designed, and an application trusted for an item reads it without a prompt. The problem is that the agent's advice makes a general-purpose CLI, which the agent itself can run, the trusted application.
Why it matters. An organization can block security find-generic-password for the agent with a PreToolUse hook, but only on managed machines, only on the CLI path, and not for items already created this way — those keep trusting security until someone edits their access control by hand. Most users never see any of this: they followed what looked like the security-conscious advice.
Related. #77697 and #89985 describe the same access-control mechanism for /usr/bin/security. #62442 concerns plugin sensitive values meant to be stored in the keychain — a product feature, not the model improvising a scheme.
A closely related security issue with a concrete exploitation path has been reported separately through the security policy, and is deliberately not described here.