Security

Last updated: 2026-05-12

Authentication & sessions

Two sign-in paths: a one-time 6-digit code emailed via Resend, or GitHub OAuth (read-only scopes read:user + user:email). Email codes have a 15-minute TTL and lock after 5 wrong attempts. Session tokens are HttpOnly + Secure + SameSite=Lax cookies with a 30-day rolling lifetime. GitHub access tokens are stored AES-GCM-256 encrypted with the user id as Additional Authenticated Data — only the rightful owner can decrypt.

Encryption in transit

HTTPS-only, HSTS preloaded. Our edge runs on Cloudflare with TLS 1.2+. Outbound deliveries (sign-in code, status alerts, digest emails, webhooks) are HTTPS-only. Webhook URLs that resolve to http:// are rejected at save time.

Encryption at rest

Account data + preferences live in Cloudflare KV, which encrypts data at rest. On top of Cloudflare's encryption we apply application-level AES-GCM-256 for anything truly sensitive (currently: GitHub OAuth tokens), keyed with the user id as AAD so a stolen blob cannot be decrypted in isolation.

Email destination verification

Adding a non-account email to your alert destinations sends a one-click confirmation link signed with HMAC-SHA256. Until the recipient confirms ownership, the address is marked "pending" and the dispatcher refuses to send to it. The same HMAC pattern powers the one-click unsubscribe link in every marketing-shaped email (RFC 8058 compatible).

Webhook signing

Generic webhook payloads carry an X-Prismix-Signature header (HMAC-SHA256 over the body, keyed with your account's signing secret) so the receiver can verify the payload originated from us.

Rate limiting

Public endpoints (sign-in code request, contact form, star toggle, read APIs) are rate-limited per IP in a KV-backed token bucket. Abusive traffic returns 429 with a Retry-After header. The public REST API publishes its cap at /api-docs.

Idempotency & abuse defence

Alert dispatch carries per-transition idempotency markers so a flapping service cannot carpet-bomb a recipient. Digest sends carry per-week / per-day markers so a retried cron tick cannot double-send. Ko-fi webhook retries are deduplicated by transaction id with a 90-day marker.

Subprocessor list

See the Privacy Policy → Subprocessors section.

Reporting a vulnerability

Use the contact form with the "Security report" topic. Please include reproduction steps and your preferred contact for follow-up. We respond within 72 hours and aim to ship a fix within 14 days for high-severity issues.

We credit reporters in the changelog (with their consent).

What's out of scope