moonD4rk/HackBrowserData · error

requires root privileges

Error message

requires root privileges

What it means

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.

Source

Thrown at masterkey/gcoredump_darwin.go:67

		if pname == name {
			if !forceRoot || proc.Eproc.Pcred.P_ruid == 0 {
				return int(proc.Proc.P_pid), nil
			}
		}
	}
	return 0, fmt.Errorf("securityd process not found")
}

type addressRange struct {
	start uint64
	end   uint64
}

// DecryptKeychainRecords dumps securityd memory, scans for the keychain master key, and uses it to
// read login.keychain-db's generic password records. Requires root.
func DecryptKeychainRecords() ([]keychainbreaker.GenericPassword, error) {
	if os.Geteuid() != 0 {
		return nil, errors.New("requires root privileges")
	}

	pid, err := findProcessByName("securityd", true)
	if err != nil {
		return nil, fmt.Errorf("failed to find securityd pid: %w", err)
	}

	// gcore appends ".PID" to the -o prefix, e.g. prefix.123
	corePrefix := filepath.Join(os.TempDir(), fmt.Sprintf("securityd-core-%d", time.Now().UnixNano()))
	corePath := fmt.Sprintf("%s.%d", corePrefix, pid)
	defer os.Remove(corePath)

	cmd := exec.Command("gcore", "-d", "-s", "-v", "-o", corePrefix, strconv.Itoa(pid))
	if err := cmd.Run(); err != nil {
		return nil, fmt.Errorf("failed to dump securityd memory: %w", err)
	}

	// vmmap identifies MALLOC_SMALL heap regions where securityd stores keys

View on GitHub (pinned to 0503d04d7a)

Solutions

  1. Re-run the tool with sudo (or as root) so securityd memory can be dumped.
  2. Use an alternative keychain master-key tier that doesn't require root if root is unavailable.
  3. Run the tool inside a root session/agent (launchd with root, ssh as root).

Example fix

// before
./hack-browser-data
// after
sudo ./hack-browser-data
Defensive patterns

Strategy: validation

Validate before calling

if os.Geteuid() != 0 {
    return errors.New("keychain decryption requires root; re-run with sudo")
}

Try / catch

pw, err := masterkey.DecryptKeychainRecords()
if err != nil && strings.Contains(err.Error(), "requires root") {
    return nil, fmt.Errorf("re-run with sudo: %w", err)
}

Prevention

When it happens

Trigger: Calling DecryptKeychainRecords (e.g. via GcoredumpRetriever) while the process is not running as root — os.Geteuid() != 0.

Common situations: Running hack-browser-data as a normal macOS user, running under sudo-less automation/CI, or the binary lacking setuid/root execution.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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