{"record":{"id":"2a8e718e4c18f890","repo":"moonD4rk/HackBrowserData","slug":"requires-root-privileges","errorCode":null,"errorMessage":"requires root privileges","messagePattern":"requires root privileges","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"masterkey/gcoredump_darwin.go","lineNumber":67,"sourceCode":"\t\tif pname == name {\n\t\t\tif !forceRoot || proc.Eproc.Pcred.P_ruid == 0 {\n\t\t\t\treturn int(proc.Proc.P_pid), nil\n\t\t\t}\n\t\t}\n\t}\n\treturn 0, fmt.Errorf(\"securityd process not found\")\n}\n\ntype addressRange struct {\n\tstart uint64\n\tend   uint64\n}\n\n// DecryptKeychainRecords dumps securityd memory, scans for the keychain master key, and uses it to\n// read login.keychain-db's generic password records. Requires root.\nfunc DecryptKeychainRecords() ([]keychainbreaker.GenericPassword, error) {\n\tif os.Geteuid() != 0 {\n\t\treturn nil, errors.New(\"requires root privileges\")\n\t}\n\n\tpid, err := findProcessByName(\"securityd\", true)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to find securityd pid: %w\", err)\n\t}\n\n\t// gcore appends \".PID\" to the -o prefix, e.g. prefix.123\n\tcorePrefix := filepath.Join(os.TempDir(), fmt.Sprintf(\"securityd-core-%d\", time.Now().UnixNano()))\n\tcorePath := fmt.Sprintf(\"%s.%d\", corePrefix, pid)\n\tdefer os.Remove(corePath)\n\n\tcmd := exec.Command(\"gcore\", \"-d\", \"-s\", \"-v\", \"-o\", corePrefix, strconv.Itoa(pid))\n\tif err := cmd.Run(); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to dump securityd memory: %w\", err)\n\t}\n\n\t// vmmap identifies MALLOC_SMALL heap regions where securityd stores keys","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/moonD4rk/HackBrowserData/blob/0503d04d7a8d0379d060268a74f1b149e5a0aad5/masterkey/gcoredump_darwin.go#L49-L85","documentation":"DecryptKeychainRecords dumps securityd memory to recover the macOS keychain master key, an operation only the root user can perform (reading another process's memory via gcore requires euid 0). The function checks os.Geteuid() upfront and refuses to run unprivileged. This implementation is only compiled with -tags keychain_gcore.","triggerScenarios":"Calling DecryptKeychainRecords (e.g. via GcoredumpRetriever) while the process is not running as root — os.Geteuid() != 0.","commonSituations":"Running hack-browser-data as a normal macOS user, running under sudo-less automation/CI, or the binary lacking setuid/root execution.","solutions":["Re-run the tool with sudo (or as root) so securityd memory can be dumped.","Use an alternative keychain master-key tier that doesn't require root if root is unavailable.","Run the tool inside a root session/agent (launchd with root, ssh as root)."],"exampleFix":"// before\n./hack-browser-data\n// after\nsudo ./hack-browser-data","handlingStrategy":"validation","validationCode":"if os.Geteuid() != 0 {\n    return errors.New(\"keychain decryption requires root; re-run with sudo\")\n}","typeGuard":null,"tryCatchPattern":"pw, err := masterkey.DecryptKeychainRecords()\nif err != nil && strings.Contains(err.Error(), \"requires root\") {\n    return nil, fmt.Errorf(\"re-run with sudo: %w\", err)\n}","preventionTips":["Check euid before attempting macOS keychain extraction.","Automate with a root launchd job or sudo-wrapped invocation.","Document the root requirement for macOS targets."],"tags":["macos","keychain","root","privileges","securityd"],"backgroundTag":"permission-denied","analyzedSha":"0503d04d7a8d0379d060268a74f1b149e5a0aad5","analyzedAt":"2026-09-06T13:38:28.707Z","contentChangedAt":"2026-09-06T13:38:28.707Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}