Security

Policy last updated 2026-04-17.

Reporting a vulnerability

If you find a security issue, email [email protected]. Encrypt with our PGP key if the issue is sensitive (request the key in your first message).

Please include:

We acknowledge within 48 hours and aim to fix critical issues within 7 days. Please do not publicly disclose a vulnerability before we've shipped a fix.

Out of scope

In scope

Recognition

We don't run a paid bug bounty at this size. If you report something material and want to be credited, we'll add you to SECURITY_HALL_OF_FAME.md in the repo once the fix ships.

Keys and tokens

Operational secret-exposure playbook

The operator-side runbook for when a secret is suspected to have leaked (accidentally committed to git, shared in a DM, pasted into a screenshot, surfaced in a log the wrong person can read). Actions are ordered by severity — start from the top.

  1. Paddle API key (PADDLE_API_KEY): rotate in the Paddle dashboard → Developer tools → Authentication, revoke the exposed key, mint a new one, then fly secrets set PADDLE_API_KEY=... -a amaneki. Audit transactions and subscriptions in Paddle for any creation you didn't initiate.
  2. Paddle webhook signing secret (PADDLE_WEBHOOK_SECRET): regenerate the notification destination in Paddle dashboard → Developer tools → Notifications, copy the new signing secret, fly secrets set PADDLE_WEBHOOK_SECRET=... -a amaneki. Replay any transaction events from the Paddle Events log if webhooks were silently dropping.
  3. Postgres URL (DATABASE_URL): change the PG role password via fly mpg users or the cluster admin console, update DATABASE_URL, deploy. Audit pg_stat_activity and the api_calls + key_audit tables for unexpected IPs.
  4. Fly API token (used by the CI deploy + backup workflows): revoke at fly tokens revoke, mint a new one with fly tokens create deploy -a amaneki, update the FLY_API_TOKEN GitHub Actions secret, re-run CI.
  5. Metrics token (METRICS_TOKEN): change once, no external exposure risk since it only reads Prometheus text.
  6. Sentry DSN: regenerate in Sentry project settings, update SENTRY_DSN secret. Worst case of unrotated leak: someone spams noise into your Sentry project.
  7. Exchange API keys (Binance/Coinbase/Bybit public data pulls): we use unauthenticated endpoints, so no keys are held — if this changes in future, rotate via each exchange's account UI.
  8. Customer-facing API keys if the incident involves a customer key hash leaking from postgres: email the affected account, instruct POST /v1/me/rotate-key, and if necessary revoke proactively in the admin UI.

General principle: rotate first, investigate second. The forensic log analysis can happen after the secret is invalidated. Every rotation above is under 10 minutes of work.

security.txt

Machine-readable disclosure info at /.well-known/security.txt.