Security.
As of
Last updated: 2 September 2026
Transport & hardening
All traffic over HTTPS (TLS 1.2+) with HSTS enforced at the GitHub Pages edge. Content-Security-Policy restricts scripts to same-origin plus plausible.io (inert since 24 September 2026) and www.googletagmanager.com, the latter loaded only after explicit consent to Google Analytics (no eval). style-src is 'self' 'unsafe-inline' — inline styles are allowed because the React app renders inline style objects, so injected <style> tags are not blocked by CSP today (a known trade-off; eliminating it would require extracting every inline style). Payment frames restricted to Stripe. MIME-sniffing blocked (nosniff), referrer leaks blocked (strict-origin-when-cross-origin). Permissions-Policy disables geolocation, camera, and microphone. CSP is declared via <meta http-equiv> in index.html; HSTS is sent by GitHub Pages itself. Note: X-Frame-Options and CSP frame-ancestors are header-only per spec and so cannot be delivered by a static host's meta tag. The domain is now served behind Cloudflare, which sets those headers at the edge: measured on 2 September 2026, the origin answers with X-Frame-Options: DENY, Permissions-Policy (camera, microphone, geolocation, payment, USB and interest-cohort disabled), Referrer-Policy: strict-origin-when-cross-origin, X-Content-Type-Options: nosniff and Strict-Transport-Security with preload. Clickjacking protection is therefore in force, not merely wished for.
Infrastructure
Static front end. GitHub Pages global edge network (Fastly CDN) with DDoS mitigation at the edge. The origin that serves the app is fully static: no application server of ours, no server-side rendering, no application code path executing on that origin. /api/* endpoints there are static JSON.
Data plane. Data lives in Supabase (managed PostgreSQL) and is read by the browser through PostgREST and a small number of Deno Edge Functions — which do process user input (JWTs, form payloads, Stripe webhooks). Authorisation is therefore not "eliminated by construction": it rests on PostgreSQL Row-Level Security and on per-function JWT verification, fail-closed. The OWASP Top-10 server-side risks the static front genuinely removes are the ones that need an application server of ours (server-side XSS, deserialisation, SSRF from the web origin); SQLi, IDOR and broken access control remain risks that are managed in Supabase, not risks that are absent.
Supabase integration
v36 introduces a runtime guard: if the injected REACT_APP_SUPABASE_ANON_KEY decodes to role=service_role, the client refuses to boot. This catches accidental service_role key leaks via CI secret mix-ups before they can reach a browser session.
Dependencies
Current runtime dependencies: React, @supabase/supabase-js, @fontsource (Fraunces variable, Geist Sans, JetBrains Mono), fflate, pdfjs-dist, topojson-client and world-atlas. package.json is always the canonical, up-to-date list. react-scripts was dropped in v36 (the project runs on Vite), removing ~1 200 transitive packages and many low-severity advisories. Dependabot opens weekly PRs for npm and Actions updates.
Responsible disclosure
Email security@analyticslegends.ai. Please allow 90 days before public disclosure. Acknowledgement within 72 hours, fix within 30 days for high-severity issues. Machine-readable at /.well-known/security.txt.
Out of scope
Issues in Stripe's hosted Checkout (report to stripe.com/security), GitHub's infrastructure (report to bounty.github.com), third-party sites we link to, social engineering of operator accounts.