Security
CSP enforcement
How Kausa enforces its Content-Security-Policy, reports violations, and responds to incidents.
Approach
Kausa rolled out CSP in three phases:
- Baseline: added
Content-Security-Policy-Report-Onlyheader with the policy below. - Reporting: added
/api/csp-report, wiredreport-uriandReporting-Endpointsinto the report-only header, deployed to production. - Enforcement: flipped from
Content-Security-Policy-Report-OnlytoContent-Security-Policy. The report-uri stays active for ongoing monitoring.
The report-only header was live in production for several days before the enforce flip with zero violations recorded across the wallet-connect flows (Phantom, Solflare, Backpack).
Current policy
default-src 'self';
script-src 'self' 'unsafe-inline' 'unsafe-eval';
style-src 'self' 'unsafe-inline';
img-src 'self' data: blob: https:;
connect-src 'self' https://api.devnet.solana.com https://api.mainnet-beta.solana.com
wss://api.devnet.solana.com wss://api.mainnet-beta.solana.com;
font-src 'self' data:;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
report-uri /api/csp-report;
report-to csp-endpointDirective rationale
| Directive | Value | Reason |
|---|---|---|
default-src | 'self' | Only load resources from the same origin by default. |
script-src | 'self' 'unsafe-inline' 'unsafe-eval' | Wallet adapter libraries (Phantom, Solflare) require inline scripts and eval for adapter detection. |
style-src | 'self' 'unsafe-inline' | Tailwind CSS and shadcn/ui inject inline styles at runtime. |
img-src | 'self' data: blob: https: | Campaign images may come from external HTTPS sources; wallet icons use data URIs. |
connect-src | Solana RPC endpoints | Wallet adapter needs RPC connections to devnet (and mainnet-beta for adapter compatibility checks). |
font-src | 'self' data: | next/font embeds fonts as data URIs. |
frame-ancestors | 'none' | Prevent clickjacking — the app should never be framed. |
base-uri | 'self' | Prevent base tag injection attacks. |
form-action | 'self' | Forms only submit to the same origin. |
Debugging future violations
-
Check the
csp_violationstable:SELECT violated_directive, blocked_uri, COUNT(*) AS cnt FROM csp_violations GROUP BY violated_directive, blocked_uri ORDER BY cnt DESC; -
Check server logs:
sudo journalctl -u kausa --since '1 hour ago' | grep csp-violation -
To fix a violation, either:
- Update the CSP directive in
next.config.tsto allow the legitimate source. - Fix the code to avoid the violation (move inline script to file, etc.).
- Update the CSP directive in
-
Document any newly allowed sources on the CSP allowlist page.
Report endpoint
POST /api/csp-report accepts both formats:
- Legacy:
application/csp-report(most browsers). - Modern:
application/reports+json(Reporting API v1).
Rate-limited to 100 requests/minute per IP. The User-Agent is hashed (SHA-256, truncated to 32 chars) before storage to avoid PII.