Implementing Content Security Policy (CSP)

Implementing Content Security Policy (CSP)

Content Security Policy deserves special attention as one of the most powerful security headers. CSP prevents XSS attacks by specifying which sources of content are trusted. Implementing CSP requires careful planning and testing:

Start with a report-only policy to identify issues:

# Apache - CSP Report-Only mode
Header always set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; report-uri /csp-report"
# Nginx - CSP Report-Only mode
add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; report-uri /csp-report" always;

Create a CSP report endpoint to collect violations:

# Apache CSP report handler
<Location /csp-report>
    SetHandler application/json
    # Log or process CSP reports
</Location>

Gradually tighten your CSP policy:

# Strict CSP with nonces for inline scripts
set $csp_nonce $request_id;
add_header Content-Security-Policy "
    default-src 'self';
    script-src 'self' 'nonce-$csp_nonce';
    style-src 'self' 'nonce-$csp_nonce';
    img-src 'self' data: https:;
    font-src 'self';
    connect-src 'self' https://api.example.com;
    media-src 'self';
    object-src 'none';
    frame-src 'self';
    frame-ancestors 'self';
    base-uri 'self';
    form-action 'self';
    upgrade-insecure-requests;
    block-all-mixed-content;
" always;

# Pass nonce to application
fastcgi_param CSP_NONCE $csp_nonce;