Skip to content
Kausa Docs
Security

CSP enforcement

How Kausa enforces its Content-Security-Policy, reports violations, and responds to incidents.

Approach

Kausa rolled out CSP in three phases:

  1. Baseline: added Content-Security-Policy-Report-Only header with the policy below.
  2. Reporting: added /api/csp-report, wired report-uri and Reporting-Endpoints into the report-only header, deployed to production.
  3. Enforcement: flipped from Content-Security-Policy-Report-Only to Content-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-endpoint

Directive rationale

DirectiveValueReason
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-srcSolana RPC endpointsWallet 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

  1. Check the csp_violations table:

    SELECT violated_directive, blocked_uri, COUNT(*) AS cnt
    FROM csp_violations
    GROUP BY violated_directive, blocked_uri
    ORDER BY cnt DESC;
  2. Check server logs:

    sudo journalctl -u kausa --since '1 hour ago' | grep csp-violation
  3. To fix a violation, either:

    • Update the CSP directive in next.config.ts to allow the legitimate source.
    • Fix the code to avoid the violation (move inline script to file, etc.).
  4. 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.