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

  1. Read the stderr text embedded in the error — it is the raw `security` output and states what the tool complained about
  2. Check `security find-generic-password -wa 'Chrome Safe Storage'` manually in a terminal to reproduce and inspect the warning
  3. Unlock the keychain first (`security unlock-keychain login.keychain-db`) or remove/repair the offending keychain in Keychain Access
  4. Fall back to another retriever: pass the keychain password to KeychainPasswordRetriever or run with root so GcoredumpRetriever succeeds
  5. 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

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


AI-assisted analysis of moonD4rk/HackBrowserData@0503d04d7a (2026-09-06). Data as JSON: /api/errors/14667ab4316ef502. Report an issue: GitHub.