CSP - Content Security Policy

What It Is

Browser security mechanism that controls which resources a webpage can load. Prevents code injection attacks (XSS, clickjacking) by restricting sources of scripts, styles, images, and other content.

How It Works

Server sends CSP headers or webpage includes CSP meta tags. Browser enforces the policy by blocking unauthorized resource loads and reporting violations.

<!-- Via meta tag -->
<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; script-src 'self' https://trusted.com">

<!-- Via HTTP header (preferred) -->
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.com

Key Directives

Content Types

  • default-src - Fallback for all other directives
  • script-src - JavaScript sources
  • style-src - CSS sources
  • img-src - Image sources
  • connect-src - AJAX, WebSocket, fetch() sources
  • font-src - Font sources
  • media-src - Audio/video sources
  • frame-src - iframe sources

Common Source Values

  • 'self' - Same origin only
  • 'none' - Block all sources
  • 'unsafe-inline' - Allow inline scripts/styles (avoid if possible)
  • 'unsafe-eval' - Allow eval() (avoid if possible)
  • https://example.com - Specific domain
  • https: - Any HTTPS source
  • data: - Data URIs
  • 'nonce-xyz123' - Specific nonce value

Common Configurations

Strict Policy

Content-Security-Policy: default-src 'self'; 
                        script-src 'self'; 
                        style-src 'self' 'unsafe-inline'; 
                        img-src 'self' data:

Development Policy

Content-Security-Policy: default-src 'self' 'unsafe-inline' 'unsafe-eval'; 
                        connect-src 'self' ws://localhost:*

CDN-Friendly Policy

Content-Security-Policy: default-src 'self'; 
                        script-src 'self' https://cdn.jsdelivr.net; 
                        style-src 'self' https://fonts.googleapis.com; 
                        font-src https://fonts.gstatic.com

Implementation Example

Express.js

app.use((req, res, next) => {
  res.setHeader('Content-Security-Policy', 
    "default-src 'self'; script-src 'self' https://trusted.com");
  next();
});
// Generate nonce
const nonce = crypto.randomBytes(16).toString('base64');
res.setHeader('Content-Security-Policy', 
  `script-src 'self' 'nonce-${nonce}'`);

// In HTML
<script nonce="${nonce}">console.log('Safe script');</script>

Report-Only Mode

Content-Security-Policy-Report-Only: default-src 'self'
  • Logs violations without blocking
  • Useful for testing before enforcement
  • Reports sent to specified URI

Key Benefits

XSS Prevention: Blocks malicious script injection Data Theft Protection: Controls where data can be sent
Clickjacking Defense: Restricts iframe embedding Mixed Content Protection: Enforces HTTPS usage

Common Gotchas

  • Inline scripts/styles blocked: Use nonces or external files
  • eval() blocked: Avoid dynamic code execution
  • Third-party widgets: May require policy adjustments
  • Legacy code: Often relies on 'unsafe-inline'

Debugging

  1. Check browser console for CSP violation messages
  2. Use Report-Only mode during development
  3. Browser dev tools show blocked resources
  4. Test with strict policy first, then relax as needed

CORS vs CSP

  • CORS: Controls incoming requests to your server
  • CSP: Controls outgoing requests from your webpage

Backlinks