moonD4rk/HackBrowserData · error

read keychain: %w

Error message

read keychain: %w

What it means

This wraps os.ReadFile failure for loginKeychainPath (~/Library/Keychains/login.keychain-db). The keychain bytes are needed to attempt unlocking with each candidate master key; without the file nothing can be decrypted.

Source

Thrown at masterkey/gcoredump_darwin.go:102

	// vmmap identifies MALLOC_SMALL heap regions where securityd stores keys
	regions, err := findMallocSmallRegions(pid)
	if err != nil {
		return nil, fmt.Errorf("failed to find malloc small regions: %w", err)
	}

	candidates, err := scanMasterKeyCandidates(corePath, regions)
	if err != nil {
		return nil, fmt.Errorf("scan master key candidates: %w", err)
	}
	if len(candidates) == 0 {
		return nil, fmt.Errorf("no master key candidates found in securityd memory")
	}

	// read keychain file once, reuse buffer for each candidate
	keychainBuf, err := os.ReadFile(loginKeychainPath)
	if err != nil {
		return nil, fmt.Errorf("read keychain: %w", err)
	}

	for _, candidate := range candidates {
		kc, err := keychainbreaker.Open(keychainbreaker.WithBytes(keychainBuf))
		if err != nil {
			continue
		}
		if err := kc.Unlock(keychainbreaker.WithKey(candidate)); err != nil {
			continue
		}

		records, err := kc.GenericPasswords()
		if err != nil {
			continue
		}
		if len(records) > 0 {
			return records, nil
		}

View on GitHub (pinned to 0503d04d7a)

Solutions

  1. Verify the file exists: `ls -la ~/Library/Keychains/login.keychain-db` for the target user.
  2. Fix HOME/SUDO_USER handling — run with the target user's home resolved explicitly rather than relying on os.UserHomeDir() under sudo.
  3. Point the tool at the correct keychain path if a custom keychain is in use (code currently hardcodes loginKeychainPath).
  4. Grant Full Disk Access to the terminal/tool if sandbox/TCC blocks reading user Library data even as root.
  5. If the user has no local login keychain (iCloud keychain only), this path is not applicable — use another extraction method.

Example fix

// before
keychainBuf, err := os.ReadFile(loginKeychainPath)
// after
keychainBuf, err := os.ReadFile(loginKeychainPath)
if err != nil {
    return nil, fmt.Errorf("read keychain %s: %w (check HOME resolves to the target user and file exists)", loginKeychainPath, err)
}
Defensive patterns

Strategy: validation

Validate before calling

home, err := os.UserHomeDir()
if err != nil {
    return err
}
kcPath := filepath.Join(home, "Library", "Keychains", "login.keychain-db")
if fi, err := os.Stat(kcPath); err != nil || fi.IsDir() {
    return fmt.Errorf("login keychain not found at %s", kcPath)
}

Try / catch

_, err := masterkey.DecryptKeychainRecords()
if err != nil && strings.Contains(err.Error(), "read keychain") {
    // resolve correct keychain path or request Full Disk Access
}

Prevention

When it happens

Trigger: Calling DecryptKeychainRecords when the login keychain file does not exist, is a symlink to a missing target, or cannot be read even as root (SIP-protected paths, APFS issues, unusual HOME).

Common situations: Running with a HOME pointing at another user or a service account so os.UserHomeDir() resolves to the wrong path; keychain renamed (custom keychain, or `login.keychain-db` missing on accounts created with iCloud-only keychains); keychain stored on an unmounted/mismatched volume; partially deleted user profile.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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