Analysis

privacycommand mounts the image, analyses the app inside, and unmounts it. That fails if the image needs a licence agreement accepted, is encrypted, or contains a .pkg installer rather than an app bundle.Mount it yourself, drag the .app out, and analyse that directly.
Most likely a stripped release build — symbol names carry much of the readability in the call-sites map. You’ll still get entitlements, signing, SDK fingerprints and strings.Electron and other runtime-hosted apps are also thin here: the interesting code is JavaScript inside an asar archive, not the Mach-O.
Ghidra isn’t installed, or privacycommand can’t find it. It is optional and not bundled — everything else works without it.
Expected unless the app came from the Mac App Store. Direct downloads and Homebrew casks have no labels to fetch. See Privacy labels.
privacycommand couldn’t read the TCC databases, which is where the granted axis of the permission matrix comes from. macOS protects them, so privacycommand itself needs Full Disk Access to open them.The matrix shows a card with a button straight into the right System Settings pane. Grant it and reopen privacycommand.Four things go missing, all of them in the permission matrix: the granted column, any row that exists only because macOS recorded a grant, the System access granted list that flags the inspected app’s own Full Disk Access, Accessibility, Screen Recording or Input Monitoring, and the Verdict column — every row reads Grant unknown, which also suppresses the Used in binary, not declared warning even though that one needs no TCC data. The rest of the static report is unaffected. See Requested, granted, used.

The helper

If you built from source, the helper’s signing team must match the app’s — CodeSignValidator rejects the XPC connection otherwise. Check both targets in Signing & Capabilities.For a release build, this usually means a damaged or partially quarantined install. Reinstall from a fresh download.
Expected, and worth knowing about. A helper with no Team Identifier — unsigned, ad-hoc signed, or Xcode’s “Sign to Run Locally” — accepts every connecting process rather than refusing them. It logs No Team ID — accepting connection (dev mode); check with log show --predicate 'process == "privacycommandHelper"' --last 5m.Set a signing team on the helper target to get the real check back. See How it protects itself.
fs_usage produces nothing for a process it can’t observe. Confirm the run actually launched the app and that the target isn’t a launcher stub that exits after spawning the real binary elsewhere.
Reinstall privacycommand, uninstall the helper from within it, then remove the app. Verify with:

Network

It needs the helper installed, and it needs destinations to block — the list is built from traffic already captured in this run. Let the app talk to something first.
The kill switch is a system-wide pf rule, not per-process. If the inspected app shares a host or CDN with something else, that is blocked too. Disarm it. See Network kill switch.
Blocking is by address. An app that re-resolves a hostname to a different IP can escape it. For a hard boundary, take the guest offline in VM mode.

auditctl

auditctl preview looks for brew at $HOMEBREW_PREFIX/bin/brew first, if that variable is set, then /opt/homebrew/bin/brew and /usr/local/bin/brew. A Homebrew installed somewhere else is invisible to it unless you point the variable at the prefix:
Or skip brew entirely with preview --all-apps, which reads /Applications and ~/Applications directly.
Pass --no-color, or set NO_COLOR in the environment — auditctl honours both. See auditctl.

Filing a useful issue

Include the privacycommand version, your macOS version and architecture, whether the helper is installed, and — if you can share it — the JSON export. Open it at github.com/privacykey/privacycommand/issues. For anything security-sensitive, don’t use a public issue — see Security.