moonD4rk/HackBrowserData · error

unlock keychain: %w

Error message

unlock keychain: %w

What it means

The keychain opened successfully but kc.Unlock(keychainbreaker.WithPassword(password)) failed; the error is wrapped as "unlock keychain: %w". Unlocking the login keychain requires the correct user login password.

Source

Thrown at masterkey/retriever_darwin.go:64

		log.Debugf("gcoredump: %v", r.err)
		return nil, nil //nolint:nilerr // intentional silent fallthrough
	}

	key, err := findStorageKey(r.records, hints.KeychainLabel)
	if err != nil {
		log.Debugf("gcoredump: %v", err)
		return nil, nil //nolint:nilerr // intentional silent fallthrough
	}
	return key, nil
}

func loadKeychainRecords(password string) ([]keychainbreaker.GenericPassword, error) {
	kc, err := keychainbreaker.Open()
	if err != nil {
		return nil, fmt.Errorf("open keychain: %w", err)
	}
	if err := kc.Unlock(keychainbreaker.WithPassword(password)); err != nil {
		return nil, fmt.Errorf("unlock keychain: %w", err)
	}
	return kc.GenericPasswords()
}

func findStorageKey(records []keychainbreaker.GenericPassword, storage string) ([]byte, error) {
	for _, rec := range records {
		if rec.Account == storage {
			return darwinParams.deriveKey(rec.Password), nil
		}
	}
	return nil, fmt.Errorf("%q: %w", storage, errStorageNotFound)
}

// KeychainPasswordRetriever unlocks login.keychain-db with the macOS login password (no root).
// Records are cached once and reused across browsers.
type KeychainPasswordRetriever struct {
	Password string

View on GitHub (pinned to 0503d04d7a)

Solutions

  1. Confirm the Password field matches the current macOS login password of the keychain owner
  2. Test the password manually: unlock the keychain in Keychain Access or via `security unlock-keychain`
  3. If the keychain password differs from the login password, supply the keychain-specific password
  4. Ensure the keychain is not locked: `security show-keychain-info login.keychain-db`

Example fix

// before
r := &masterkey.KeychainPasswordRetriever{Password: "password123"}
// after
pw := os.Getenv("USER_LOGIN_PASSWORD")
if pw == "" {
	return nil, errors.New("USER_LOGIN_PASSWORD not set")
}
r := &masterkey.KeychainPasswordRetriever{Password: pw}
Defensive patterns

Strategy: validation

Validate before calling

if r.Password == "" {
	return errors.New("keychain password required")
}
// optional pre-check
cmd := exec.Command("security", "unlock-keychain", "-p", r.Password)
if err := cmd.Run(); err != nil {
	return fmt.Errorf("password rejected: %w", err)
}

Type guard

func (r *masterkey.KeychainPasswordRetriever) Configured() bool {
	return r.Password != ""
}

Try / catch

key, err := r.RetrieveKey(hints)
if err != nil && strings.HasPrefix(err.Error(), "unlock keychain:") {
	return nil, errors.New("wrong login password for keychain")
}

Prevention

When it happens

Trigger: KeychainPasswordRetriever.RetrieveKey with a Password that is empty-check-passed but wrong, or when the keychain is locked and cannot be unlocked with the supplied password.

Common situations: User supplied the login password of a different account, the password was changed recently and the keychain kept the old one, or automation runs headless where the UI unlock prompt can't be answered.

Related errors


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