feat: Nonce-based CSP implementation
Summary
DRAFT - Work in Progress
This MR implements nonce-based Content Security Policy, which provides significantly stronger XSS protection compared to unsafe-inline.
Background
With 'unsafe-inline' in script-src (Phase 2), CSP provides ~40% XSS protection. With nonces, it provides ~95% protection because:
- Inline scripts without the correct nonce are blocked
- Attacker-injected scripts don't have the nonce
-
'strict-dynamic'allows legitimately loaded scripts to load additional scripts
Implementation
Middleware (apps/blog/middleware.ts)
- Generates cryptographically secure nonce using
crypto.randomUUID() - Builds CSP header with nonce in script-src and style-src
- Uses
'strict-dynamic'for script loading chains - Passes nonce to app via
x-nonceheader
Layout (apps/blog/app/layout.tsx)
- Reads nonce from headers
- Passes nonce to Script components
What's Implemented
- Nonce generation in middleware
- CSP header with nonce
- Nonce passed to layout
- Script component uses nonce
What Still Needs Work
- Wallet app implementation
- All Script components in the app need nonce prop
- Third-party script handling (Twitter embeds, etc.)
- HBAuth/Beekeeper WASM testing
- Hive Keychain compatibility testing
- Comprehensive E2E testing
- Switch from Report-Only to enforcing mode
Dependencies
This MR depends on:
- MR !779 (merged) - Add security response headers
- MR !780 (merged) - Add CSP violation report endpoint
- MR !781 (merged) - Add CSP Report-Only header
Test Plan
Before merging:
- Deploy to staging
- Verify nonce in CSP header changes per request
- Test all app functionality
- Test all embedded content
- Test authentication flows
- Monitor CSP violations
- Verify no console errors
Notes
This is marked as draft because it requires:
- Phase 2 (Report-Only) to be deployed and monitored first
- Comprehensive testing before switching to enforcing mode
- Possible adjustments based on Report-Only violations