1 min read
The CSP nonce that bit back
A field report on strict CSP with htmx: what broke, what the spec actually says, and the one line that fixes it.
Strict CSP with unsafe-inline removed is the right default, and htmx
cooperates better than most frameworks. But three details will bite:
-
htmx injects indicator styles at runtime. A
<style>tag from JS is
inline CSS, whichstyle-src 'self'blocks. Disable it:
<meta name="htmx-config" content='{"includeIndicatorStyles":false}'>
and ship the styles yourself. -
Nonces must rotate per request or they're as useless as hashes.
Middleware: generate 16 random bytes, base64, put it in both the CSP
header and the templ render context. -
strict-dynamicis load-bearing. It lets your nonced bootstrap
script load its own modules while the page stays closed to injected
scripts. Without it, every dynamic import becomes a CSP violation.
The win: zero inline handlers, zero allowlisted domains, and a policy you
can actually reason about.