Skip to content

Security: Robby955/ConfigPulse

Security

docs/security.md

Security Model

How Config Pulse protects user data, prevents abuse, and secures the notification pipeline.


Rate Limiting

The API enforces four tiers of rate limiting to prevent abuse and brute-force attacks:

Tier Limit Endpoints
General 100 requests/min All endpoints
Email 10 requests/15 min Any endpoint that triggers email delivery
Auth 20 requests/15 min Login, registration, email verification
Lookup 10 requests/min Email existence checks

The lookup tier specifically prevents email enumeration — an attacker cannot rapidly check which email addresses have Config Pulse accounts.


Row Level Security

All user data is stored in Supabase with PostgreSQL Row Level Security (RLS) policies. This provides defense in depth: even if the API server has a bug that bypasses application-level access checks, the database itself enforces that users can only read and write their own records.

RLS policies cover user profiles, device registrations, check-in history, sponsor relationships, and subscription state.


Notification Security

Sponsor alerts are the most sensitive feature — they send information to third parties. Multiple safeguards prevent misuse:

Sponsor verification: The system confirms that the sponsor email in a notification request matches the registered sponsor for that user. Alerts cannot be sent to arbitrary addresses.

Subscription gating: Only premium subscribers can trigger sponsor alerts. Free-tier users get DNS blocking but no notification pipeline.

Per-user cooldown: A 1-hour cooldown prevents duplicate alert types for the same user. If a DNS_DISABLED alert fires, another DNS_DISABLED alert for the same user won't send for at least an hour.

Per-sponsor rate limit: Maximum 5 emails per hour to any single sponsor address, regardless of how many users have designated that sponsor. This protects individuals who sponsor multiple people.

Timing context: Every alert includes the last known check-in time and heartbeat timestamp. Sponsors receive actionable information, not just "something happened."


Input Validation

Profile generation: All user-provided strings are XML-escaped before insertion into .mobileconfig payloads. This prevents XML injection attacks that could alter profile behavior.

Phone numbers: Validated against E.164 international format before storage or use with Twilio.

Email addresses: Format validation plus domain verification.

UUIDs: Format enforcement on all identifier fields — prevents injection via malformed identifiers.


Privacy

Config Pulse is designed to verify compliance without surveillance:

What is stored: Check-in timestamps, profile status at check-in time, device metadata (OS version, app version), aggregate blocked-domain statistics, and alert delivery logs.

What is NOT stored: Browsing history, DNS query logs (the resolver processes queries in memory and does not log them), message content, location data (unless explicitly enabled by the user), or any traffic content.

The DNS resolver specifically does not retain query logs. Blocked domains return NXDOMAIN; allowed domains are forwarded to Google DNS. Neither case produces a stored record of the user's browsing activity.


Admin Access

Admin endpoints are protected by authentication and scoped to authorized accounts only. An OWNER_NOTIFY_BYPASS_TOKEN (a random UUID regenerated on every server boot) allows testing alert flows in development without triggering real notifications.


© 2026 Robert Sneiderman. All rights reserved.

There aren’t any published security advisories