Privacy & data flow
The short version: your fleet's data never leaves your Mac. The longer version is on this page — what Noxen reads, where it stores it, what (if anything) syncs to iCloud, and what outbound network traffic Noxen actually makes.
What gets read on your Mac
~/.ssh/config— only on explicit import via SSH config import. Never read otherwise.- Referenced SSH private keys — read once at
host enrolment time, copied into the macOS Keychain, then
the on-disk key file is never re-read. The Keychain entry is
scoped to the Noxen app group
(
group.com.paulsnyman.noxen) so the scheduled-scan agent can read it for nightly runs. - System network info — your primary interface's subnet for LAN discovery defaults. Read once when you open the discovery UI; not transmitted anywhere.
What gets stored locally
- SwiftData
(
~/Library/Application Support/app.noxen/default.store) — Host catalog (display name, hostname, port, username, tags), Scan history (timestamps, status), Findings (severity, category, title, detail, remediation), Installed package inventory (per-host, time-stamped). - Keychain — SSH private keys, license keys.
Marked
kSecAttrSynchronizable=falseso iCloud Keychain doesn't replicate them across your other Macs. - App Support —
cves-latest.sqlite(the imported CVE feed),noxen-feed-baseline-YYYYMMDD.jsonl.gz(the downloaded snapshot),custom-checks/(your user-authored checks). - UserDefaults — preferences (theme, scheduled-scan time, webhook URLs), feature flags, the per-day "last checked" timestamps used to throttle feed polls.
What syncs to iCloud (when enabled)
Optional and off by default. When you enable iCloud sync in
Settings, a CloudKit private database in the
iCloud.com.paulsnyman.noxen container replicates:
- Host catalog entries (names, hostnames, ports, usernames, tags).
- Scan records (timestamps, status, scan IDs).
- Finding records (severity, category, title, detail, remediation, KEV/EPSS tags).
Explicitly excluded from CloudKit sync:
- SSH private keys — Keychain marked non-synchronisable.
- License keys — same.
- The CVE feed snapshot itself — it's the same on every Mac, no point replicating.
- Webhook URLs containing tokens — these are stored in Keychain (not SwiftData) so they don't sync even if you turn iCloud on.
iCloud sync is what powers the iOS view-only companion — your phone sees the host catalog and findings via the same private CloudKit container, no separate auth or backend required.
What outbound network traffic Noxen makes
Three (and only three) destinations:
feed.noxen.app- The signed CVE feed manifest + snapshot. One GET per check (cadence depends on tier — see CVE feed reference). No request body. The Cloudflare worker behind it sees the request IP (any standard CDN log). It does not see anything about your fleet — there's no fleet identifier in the request.
noxen.app/appcast.xml- Sparkle update check. One GET per app launch (cached for 24 h). Used to determine if a newer Noxen build is available. Exposes your installed Noxen version and OS version (Sparkle's default headers); doesn't expose anything about your fleet.
SSH / TCP / HTTP(S) to your enrolled hosts- Initiated by you (manual scan, scheduled scan, batch scan). Goes to your own hosts at IPs you specify; doesn't touch any third-party network. Encrypted (SSH for inventory, TLS for HTTPS probes); plaintext for HTTP probes only on ports you've enrolled.
What Noxen does NOT do
- Send fleet inventory to any server. CVE matching happens in-process on your Mac after the feed is downloaded.
- Send scan results to any server. Even when webhooks are configured, the webhook target is your own Slack / Discord / Teams / custom endpoint — Noxen doesn't relay through its own servers.
- Use third-party analytics. The marketing site
(
noxen.app) loads Google Analytics, but the Mac app itself ships zero analytics or telemetry. - Scan networks you didn't enrol. Discovery only runs on the subnet you specify; scans only target hosts you've explicitly added.
Runtime audit
Settings → Advanced → Runtime audit shows a live snapshot of Noxen's privacy posture:
- Sparkle public key present + valid.
- App Group container reachable.
- CloudKit container configured (or "no iCloud account" if not).
- Debug bypass disabled (must be false in shipping builds — see the entitlement-gating tests).
The audit re-runs on every launch and surfaces anything anomalous as a settings-pane warning. Useful when triaging "is my install configured correctly?" questions.
Privacy policy
The full legal text — including processor disclosures and EU data-rights walkthrough — lives at noxen.app/privacy.