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:
- A description of the vulnerability and its impact
- Minimal reproduction steps, including any request headers / payloads
- Whether you're comfortable being credited publicly
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
- Missing best-practice HTTP headers on legacy endpoints — we track these but don't treat them as vulns unless they enable an exploit
- Rate-limit bypass via key rotation alone — the rate limit is a traffic-shaping tool, not a security boundary
- Self-XSS, issues requiring physical access, or any attack on third-party services (Paddle, Binance, Cloudflare) that we embed
In scope
- Authentication bypass on any authed endpoint
- Exposure of another customer's API key, webhook secret, or billing metadata
- Server-side request forgery, remote code execution, SQL injection, account takeover
- Signature-bypass on our outbound webhook HMAC (
X-Amaneki-Signature) - Privilege escalation inside the named-preset / webhook subscription systems
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
- API keys: rotate anytime via
POST /v1/me/rotate-key. The previous key is invalidated instantly. - Webhook signing secrets: shown once at subscription creation. To rotate, delete the subscription and create a new one.
- Paddle API keys: never loaded into the landing or SDK; only the server-side key in Fly secrets.
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.
- Paddle API key (
PADDLE_API_KEY): rotate in the Paddle dashboard → Developer tools → Authentication, revoke the exposed key, mint a new one, thenfly secrets set PADDLE_API_KEY=... -a amaneki. Audittransactionsandsubscriptionsin Paddle for any creation you didn't initiate. - 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. - Postgres URL (
DATABASE_URL): change the PG role password viafly mpg usersor the cluster admin console, updateDATABASE_URL, deploy. Auditpg_stat_activityand theapi_calls+key_audittables for unexpected IPs. - Fly API token (used by the CI deploy + backup workflows): revoke at
fly tokens revoke, mint a new one withfly tokens create deploy -a amaneki, update theFLY_API_TOKENGitHub Actions secret, re-run CI. - Metrics token (
METRICS_TOKEN): change once, no external exposure risk since it only reads Prometheus text. - Sentry DSN: regenerate in Sentry project settings, update
SENTRY_DSNsecret. Worst case of unrotated leak: someone spams noise into your Sentry project. - 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.
- 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.