Security
Disclosure path, posture, and the honest gaps.
BeaconNZ is in Phase 0. The security posture below is the truth of the platform today — controls in place are listed alongside controls in progress, with target phases. We will not claim what we do not hold.
Disclosure path
Found something? Tell us.
Email security@beaconnz.nz. We acknowledge within 72 hours. We will not pursue legal action against good-faith researchers who report responsibly and avoid disrupting the service or accessing user data beyond what is necessary to demonstrate the issue.
- Acknowledgement within 72 hours, including weekends.
- Triage and timeline within 7 days for high-severity reports.
- Public credit on resolution unless you request otherwise.
- Coordinated disclosure: please give us reasonable time to ship a fix before publishing.
Threat model
What we are protecting, and against whom.
BeaconNZ's security posture is shaped by what an attacker most plausibly wants to do here. The highest-severity outcomes — in increasing impact — are:
- Issuing false alerts at warning or emergency severity that reach the public or operators. Defended by named-operator issuance, append-only audit, and a refusal-by-default policy in the alert engine.
- Suppressing real alerts by tampering with ingest, routing, or geofence logic. Defended by signed source feeds where available, redundant ingest paths, and severity-model invariants enforced at build time.
- Exposing user-zone data — the saved areas that map a user to a place. Defended by server-side zone storage with anonymised tier tokens, and a hard rule against per-user analytics on location-bearing surfaces.
- Disabling the service during an event. Defended by NZ-resident infrastructure with active-passive failover targets, plus public read paths cached at the CDN edge so the map remains available even under origin pressure.
Lower-severity outcomes (defacement, account compromise on individual operator identities, analytics scraping) are addressed but not detailed here; assume standard-of-care defences in depth.
In place today
Controls already shipped and operational.
NZ-sovereign hosting
Operational data lives in NZ — Catalyst Cloud (Wellington) and AWS Auckland (ap-southeast-2). It does not leave the country. Cloudflare CDN serves public assets only.
TLS 1.3 in transit
All public surfaces and inter-service traffic use TLS 1.3. HSTS enabled on production hostnames; certificate management via ACME with short-lived certs.
Encryption at rest
Postgres data volumes use platform-level encryption at rest (AES-256). Object storage (R2 / MinIO) likewise. Backup volumes encrypted independently.
Append-only audit trail at issuance
Every alert at warning or emergency severity carries an issuance audit row tied to a named operator. Audit rows are append-only by schema constraint, not policy.
Severity model alignment, enforced at compile time
The severity ladder (info · watch · advisory · warning · emergency) is shared across the Rust geofence engine and the TS API. Drift between them would break alerting silently, so the build refuses to proceed when the two sides diverge.
Open source surface
Severity model, ingest pipeline, and alert engine are open and inspectable. Independent review is welcome and acted on; we publicly credit responsible disclosures.
In progress
What we are working toward.
Formal pentest
Target: Phase 1.5
Targeted before public-alpha cutover. Will be conducted by an NZ-based firm with an Aotearoa security clearance posture; report summary will be published to this page.
SOC 2 Type 1 attestation
Target: Phase 2
On the path. We will not claim it before it is held. The current control set already maps to most relevant Trust Services Criteria; the gap is documentation and external attestation.
HSM-backed signing keys for issuance
Target: Phase 2
Critical-tier alerts will be signed by HSM-backed keys with hardware-rooted access controls. Currently signed by software keys with rotation policy.
Bug bounty programme
Target: Phase 2
No formal bounty yet. Until then: responsible disclosures get acknowledged within 72 hours, public credit on resolution unless requested otherwise, and a small honorarium where appropriate.
Telemetry
What we send to third parties, and what we do not.
Application errors and a sampled subset of performance traces from apps/web are forwarded to Sentry for error monitoring. This is the only third-party data egress on the web tier. No analytics, advertising, or behavioural tracking is loaded.
Forwarded: stack traces, request URLs (with zone and operator identifiers replaced by the literal string [id]), HTTP status codes, browser/runtime metadata, and a release identifier.
Never forwarded: saved-zone polygons or coordinates, lat/lon query parameters (redacted before send), user identifiers beyond a per-session opaque token, IP address (Sentry's sendDefaultPii is disabled), or any payload from the saved-zone subscription path. Session Replay is explicitly disabled.
Traces are sampled at 10%. Data scrubbing is enforced in code on both the server and client SDKs (see apps/web/src/instrumentation.ts and the client equivalent) so even an SDK upgrade cannot ship a less-scrubbed event without a code change reviewed in PR.
Out of scope
The hard constraints on the principles page are out of scope for any disclosure or contractual negotiation. They will not be softened to accommodate an exploit, a customer request, or a procurement deadline. If a class of vulnerability exists only because of a red line we hold, the answer is to refuse the surface that creates the class.