Add baseline HTTP security headers in Caddy (B-43)
Caddy adds none of these on its own. Add HSTS, X-Content-Type-Options, X-Frame-Options, Referrer-Policy and a CSP scoped to default-src 'self' plus the one external asset (Google Fonts). script-src/style-src need 'unsafe-inline' because both SPAs rely on inline onclick handlers and style="" attributes throughout — removing those is a separate, larger refactor. Validated with `caddy validate` and a live container curl check. Adds a static regression test asserting the header directives stay present in the Caddyfile, since nothing else in the Python suite exercises it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
# Known bugs
|
||||
|
||||
A second full-codebase audit on 2026-07-27 found **25 further issues** (4 critical, 6 high,
|
||||
7 medium, 8 low), listed below as B-43 … B-49. B-25 through B-42 are fixed (see "Previously
|
||||
fixed" below) — no Critical-, High- or Medium-severity finding remains open; the remaining 7 are
|
||||
7 medium, 8 low), listed below as B-44 … B-49. B-25 through B-43 are fixed (see "Previously
|
||||
fixed" below) — no Critical-, High- or Medium-severity finding remains open; the remaining 6 are
|
||||
Low/hygiene. The 139-test suite was green at the time of the audit, so none of these were caught
|
||||
by existing coverage — every fix lands with a regression test (the eighteen fixes so far brought
|
||||
the suite from 139 to 224).
|
||||
by existing coverage — every fix lands with a regression test (the nineteen fixes so far brought
|
||||
the suite from 139 to 230).
|
||||
|
||||
The recurring pattern across the open findings is worth stating once: the code is rigorous
|
||||
about the failure modes that have actually been hit, and silent about the ones that have not.
|
||||
@@ -18,15 +18,6 @@ admin auth, single-process assumptions, no user-facing history, etc.) are docume
|
||||
|
||||
## Low / hygiene
|
||||
|
||||
### B-43 — No HTTP security headers
|
||||
|
||||
The [Caddyfile](Caddyfile) sets no CSP, no `X-Frame-Options`/`frame-ancestors`, and no HSTS
|
||||
(Caddy does not add it on its own). The JWT lives in `localStorage`, so any XSS exfiltrates
|
||||
it, and the page is iframeable.
|
||||
**Fix:** a `header` block in the Caddyfile with `Strict-Transport-Security`,
|
||||
`X-Content-Type-Options: nosniff`, `Referrer-Policy` and a CSP tight enough for two static
|
||||
pages with no external assets (`default-src 'self'`).
|
||||
|
||||
### B-44 — README and CLAUDE.md contradict each other
|
||||
|
||||
The README says to run `uvicorn --reload` directly and
|
||||
@@ -83,6 +74,7 @@ already does.
|
||||
- **B-30** — a lost scripthash subscription meant a user's deposits were never credited, with no periodic safety net
|
||||
- **B-31** — resubscribing on reconnect ran serially before anything else started, freezing the chain tip (and so an in-flight draw) for the whole sweep
|
||||
- **B-42** — Swagger/ReDoc/the raw OpenAPI JSON enumerated the entire API surface, admin endpoints included, to anyone who requested them; now off by default and gated behind `ENABLE_API_DOCS`
|
||||
- **B-43** — the Caddyfile sent no CSP, no `X-Frame-Options`/`frame-ancestors`, and no HSTS, on a page whose JWT lives in `localStorage`
|
||||
- **B-32** — an RBF bump could retry forever below BIP125's relay-mandated minimum fee delta, with no ceiling on the fee rate either
|
||||
- **B-33** — `POST /auth/login` had no rate limiting, so a password could be brute-forced against an enumerable username list
|
||||
- **B-34** — password change/reset didn't invalidate already-issued JWTs, so a stolen token survived a change meant to lock it out
|
||||
@@ -95,7 +87,7 @@ already does.
|
||||
- **B-41** — confirmation/reconciliation depended on a verbose `blockchain.transaction.get` reply many Electrum servers reject, and abandonment relied on fragile substring-matching of an error message
|
||||
|
||||
See git history for the fix-by-fix breakdown (commits `f13f685`, `50a43ae`, `933760e`, and the
|
||||
B-28/B-29/B-30/B-31/B-32/B-33/B-34/B-35/B-36/B-37/B-38/B-39/B-40/B-41/B-42 fixes). Suite grew from 139 to 224 tests over the eighteen.
|
||||
B-28/B-29/B-30/B-31/B-32/B-33/B-34/B-35/B-36/B-37/B-38/B-39/B-40/B-41/B-42/B-43 fixes). Suite grew from 139 to 230 tests over the nineteen.
|
||||
|
||||
A full-codebase audit on 2026-07-26 (commit `d4e0974`) found 24 bugs across every Python
|
||||
module under `app/`, both static frontends, and the Docker/Caddy deployment — 5 critical,
|
||||
|
||||
Reference in New Issue
Block a user