Skip to content

fix(security): hardening round two after the post-outage audit - #13

Merged
devinder-dev merged 1 commit into
mainfrom
fix/hardening-phase3
Sep 27, 2026
Merged

devinder-dev merged 1 commit into
mainfrom
fix/hardening-phase3

Conversation

@devinder-dev

Copy link
Copy Markdown
Owner

Why

The audit after the 2026-09-23 outage found no critical issues and a set of medium/low ones. None was being exploited; each was cheap to close. Full table in ADR 55.

What

  • Remove /health/whoami — a public test bench for forged IP headers
  • clientIp: trusted header configured but absent → TCP peer, never X-Forwarded-For
  • Rate-limit keys per IPv6 /64 (IPv4-mapped folds to IPv4); audit rows keep the full address
  • Argon2id behind a bounded gate: 2 active, 20 waiting, then 503 + Retry-After. The gate sits outside verifyPassword's try, so "busy" is never counted as a wrong password
  • Refuse DEMO_MODE with a live Stripe key; require an https FRONTEND_URL in production, trailing slashes stripped
  • Set-password token moved to the URL fragment and wiped from the address bar; redacted from the console mail transport in production
  • Error handler forwards 4xx messages from Fastify (FST_*) only; library 4xx (Stripe) become a 500 and reach Sentry

Tests

Backend 480 pass (new: concurrency, env-rules via child processes, mailer-redaction, IPv6 keys, error-handler cases). Frontend 21 unit (new SetPasswordPage.test.tsx), 2 Playwright e2e.

Production config check

Current Render settings pass the new boot rules: FRONTEND_URL is https, Stripe is a test key, DATABASE_URL carries no sslmode.

- remove /health/whoami (a public test bench for forged IP headers)
- clientIp: header configured but absent -> TCP peer, never X-Forwarded-For
- rate-limit keys per IPv6 /64; IPv4-mapped folds to IPv4
- Argon2id behind a bounded gate (2 active, 20 waiting, then 503 +
  Retry-After); gate sits outside verifyPassword's try so "busy" is never
  counted as a wrong password
- refuse DEMO_MODE with a live Stripe key; require https FRONTEND_URL in
  production and strip trailing slashes
- set-password token in the URL fragment, wiped from the address bar;
  redacted from the console mail transport in production
- error handler forwards 4xx messages from Fastify (FST_*) only; library
  4xx such as Stripe's become a 500 and reach Sentry
- ADR 55
@vercel

vercel Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
fakturly-app Ready Ready Preview Sep 27, 2026 2:50pm UTC

@devinder-dev
devinder-dev merged commit 3b354d1 into main Sep 27, 2026
8 checks passed

This branch was successfully deployed

1 active deployment
Preview — b035f9db Deployed Sep 27, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant