{"record":{"id":"0153e1a437e47e8a","repo":"moonD4rk/HackBrowserData","slug":"q-w","errorCode":null,"errorMessage":"%q: %w","messagePattern":"%q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"masterkey/retriever_darwin.go","lineNumber":75,"sourceCode":"\nfunc loadKeychainRecords(password string) ([]keychainbreaker.GenericPassword, error) {\n\tkc, err := keychainbreaker.Open()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"open keychain: %w\", err)\n\t}\n\tif err := kc.Unlock(keychainbreaker.WithPassword(password)); err != nil {\n\t\treturn nil, fmt.Errorf(\"unlock keychain: %w\", err)\n\t}\n\treturn kc.GenericPasswords()\n}\n\nfunc findStorageKey(records []keychainbreaker.GenericPassword, storage string) ([]byte, error) {\n\tfor _, rec := range records {\n\t\tif rec.Account == storage {\n\t\t\treturn darwinParams.deriveKey(rec.Password), nil\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"%q: %w\", storage, errStorageNotFound)\n}\n\n// KeychainPasswordRetriever unlocks login.keychain-db with the macOS login password (no root).\n// Records are cached once and reused across browsers.\ntype KeychainPasswordRetriever struct {\n\tPassword string\n\n\tonce    sync.Once\n\trecords []keychainbreaker.GenericPassword\n\terr     error\n}\n\nfunc (r *KeychainPasswordRetriever) RetrieveKey(hints Hints) ([]byte, error) {\n\tif r.Password == \"\" {\n\t\treturn nil, fmt.Errorf(\"keychain password not provided\")\n\t}\n\n\tr.once.Do(func() {","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/moonD4rk/HackBrowserData/blob/0503d04d7a8d0379d060268a74f1b149e5a0aad5/masterkey/retriever_darwin.go#L57-L93","documentation":"findStorageKey scanned all unlocked keychain generic-password records and found no record whose Account matches the requested storage name. It returns the sentinel errStorageNotFound wrapped with the quoted storage name. This means the browser's encryption key is not stored under that account in the keychain.","triggerScenarios":"RetrieveKey calls findStorageKey(records, storage) after a successful keychain load, and no rec.Account == storage match exists; also reachable directly in tests.","commonSituations":"The target browser (e.g. Chrome/Edge on macOS) never saved its Safe Storage key, the storage name in Hints doesn't match the actual keychain service/account string, or the user uses a browser version that stores keys elsewhere.","solutions":["Verify the storage name in Hints matches the keychain account exactly (e.g. \"Chrome Safe Storage\")","Dump matching records with `security find-generic-password -s \"Chrome Safe Storage\"` to see actual accounts","Confirm the browser has been run at least once so it stored its Safe Storage key","Handle errStorageNotFound via errors.Is and fall back to another retriever"],"exampleFix":"// before\nkey, err := retriever.RetrieveKey(hints)\nreturn key, err\n// after\nkey, err := retriever.RetrieveKey(hints)\nif errors.Is(err, masterkey.ErrStorageNotFound) {\n\tlog.Warnf(\"no keychain record for %q, skipping\", hints.Storage)\n\treturn nil, nil\n}\nreturn key, err","handlingStrategy":"fallback","validationCode":"out, err := exec.Command(\"security\", \"find-generic-password\", \"-a\", storage).Output()\nfound := err == nil && len(out) > 0","typeGuard":"func isStorageNotFound(err error) bool {\n\treturn errors.Is(err, masterkey.ErrStorageNotFound)\n}","tryCatchPattern":"key, err := r.RetrieveKey(hints)\nif errors.Is(err, masterkey.ErrStorageNotFound) {\n\tkey, err = fallbackRetriever.RetrieveKey(hints)\n}","preventionTips":["Confirm the browser stored its Safe Storage key (launch it once)","Match the storage account string exactly as it appears in the keychain","Register a fallback retriever for machines without the record"],"tags":["macos","keychain","not-found","record-lookup"],"backgroundTag":"record-not-found","analyzedSha":"0503d04d7a8d0379d060268a74f1b149e5a0aad5","analyzedAt":"2026-09-06T13:38:28.707Z","contentChangedAt":"2026-09-06T13:38:28.707Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}