moonD4rk/HackBrowserData · error
keychain: %s
Error message
keychain: %s
What it means
SecurityCmdRetriever on macOS runs `security find-generic-password -wa <storage>` to read the Chromium safe-storage secret from the login keychain. The command exited 0 (so the prompt was accepted and the item was found), but something was written to stderr — the library treats any non-empty stderr on a successful run as a failure rather than decrypting with possibly-bad data.
Source
Thrown at masterkey/retriever_darwin.go:151
var stdout, stderr bytes.Buffer
cmd := exec.CommandContext(ctx, "security", "find-generic-password", "-wa", strings.TrimSpace(storage)) //nolint:gosec
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
return nil, fmt.Errorf("security command timed out after %s", securityCmdTimeout)
}
// `security` exits non-zero with empty stderr when the user denies the prompt or mistypes;
// surface that instead of the cryptic "exit status 128 ()".
stderrStr := strings.TrimSpace(stderr.String())
if stderrStr == "" {
return nil, fmt.Errorf("security command: %w (likely keychain access denied or wrong password)", err)
}
return nil, fmt.Errorf("security command: %w (%s)", err, stderrStr)
}
if stderr.Len() > 0 {
return nil, fmt.Errorf("keychain: %s", strings.TrimSpace(stderr.String()))
}
secret := bytes.TrimSpace(stdout.Bytes())
if len(secret) == 0 {
return nil, fmt.Errorf("keychain: empty secret for %s", storage)
}
return darwinParams.deriveKey(secret), nil
}
// DefaultRetrievers wires the macOS V10 chain (the only tier Chromium uses here), first success wins:
// 1. GcoredumpRetriever — CVE-2025-24204 exploit (root only)
// 2. KeychainPasswordRetriever — direct unlock, skipped when password is empty
// 3. SecurityCmdRetriever — `security` CLI fallback (may prompt)
func DefaultRetrievers(keychainPassword string) Retrievers {
chain := []Retriever{&GcoredumpRetriever{}}
if keychainPassword != "" {
chain = append(chain, &KeychainPasswordRetriever{Password: keychainPassword})View on GitHub (pinned to 0503d04d7a)
Solutions
- Read the stderr text embedded in the error — it is the raw `security` output and states what the tool complained about
- Check `security find-generic-password -wa 'Chrome Safe Storage'` manually in a terminal to reproduce and inspect the warning
- Unlock the keychain first (`security unlock-keychain login.keychain-db`) or remove/repair the offending keychain in Keychain Access
- Fall back to another retriever: pass the keychain password to KeychainPasswordRetriever or run with root so GcoredumpRetriever succeeds
- Upgrade macOS/security tooling if the stderr is a known benign warning
Example fix
null
Defensive patterns
Strategy: try-catch
Validate before calling
// Best-effort pre-check (may still prompt)
cmd := exec.Command("security", "find-generic-password", "-wa", "Chrome Safe Storage")
var stderr bytes.Buffer; cmd.Stderr = &stderr
if err := cmd.Run(); err != nil { /* denied or wrong password */ } Try / catch
key, err := retriever.RetrieveKey(hints)
if err != nil {
if strings.Contains(err.Error(), "keychain: ") {
log.Warnf("security CLI warned: %v — trying password retriever", err)
}
} Prevention
- Prefer KeychainPasswordRetriever with the login password to avoid `security` CLI quirks
- Run the `security` command manually once per macOS version to surface benign stderr warnings
- Keep the chain configured (Gcoredump + password + CLI) so stderr failures fall through to another tier
- Read the embedded stderr in the error message before assuming keychain corruption
When it happens
Trigger: `security` exits 0 but prints to stderr, e.g. warnings about keychain state, deprecated output, or partial access notices emitted alongside the secret. retrieveKeyOnce unconditionally fails in that case.
Common situations: macOS versions where `security` emits benign warnings (e.g. keychain migration notices, securityd hiccups) while still succeeding; locked-but-auto-unlocking keychains; unusual keychain search paths.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- security command: %w (likely keychain access denied or wrong
- security command: %w (%s)
- security command timed out after %s
- requires root privileges
- keychain gcore dump not built in (rebuild with -tags keychai
AI-assisted analysis of moonD4rk/HackBrowserData@0503d04d7a (2026-09-06).
Data as JSON: /api/errors/14667ab4316ef502.
Report an issue: GitHub.