Content-Security-Policy header example

Complete guide to implementing Content Security Policy (CSP) headers for website security.

What is CSP?

Content Security Policy is a security header that helps prevent Cross-Site Scripting (XSS), clickjacking, and other code injection attacks by specifying which content sources are trusted.

Basic Example

Header always set Content-Security-Policy "default-src 'self'"

This allows resources only from your own domain.

Comprehensive Example

Header always set Content-Security-Policy "default-src 'none'; script-src 'self'; style-src 'self'; img-src data: 'self'; connect-src 'self'; font-src 'self'; object-src 'none'; media-src 'self'; frame-src 'none'; frame-ancestors 'none'; form-action 'self'; manifest-src 'self'; base-uri 'none'; upgrade-insecure-requests;"

Directive Breakdown

default-src 'none'

Blocks all content by default. You must then explicitly allow each content type.

script-src 'self'

Allow JavaScript only from your own domain.

Example allowing specific domains:

script-src 'self' https://cdnjs.cloudflare.com https://code.jquery.com

style-src 'self'

Allow CSS only from your domain.

Example with Google Fonts:

style-src 'self' https://fonts.googleapis.com

img-src data: 'self'

Allow images from your domain and inline data URLs (base64).

Example with CDN:

img-src 'self' data: https://cdn.example.com

font-src 'self'

Allow fonts from your domain.

Example with Google Fonts:

font-src 'self' https://fonts.gstatic.com

connect-src 'self'

Allow AJAX, WebSocket, and EventSource connections to your domain.

frame-src 'self'

Allow iframes from your domain.

Example with trusted embeds:

frame-src 'self' https://www.youtube.com https://player.vimeo.com

frame-ancestors 'none'

Prevent your site from being embedded in iframes (clickjacking protection).

form-action 'self'

Allow forms to submit only to your domain.

object-src 'none'

Block Flash and other plugins.

media-src 'self'

Allow audio/video from your domain.

manifest-src 'self'

Allow web app manifests from your domain.

base-uri 'none'

Prevent manipulation of the <base> tag.

upgrade-insecure-requests

Automatically upgrades HTTP requests to HTTPS.

Real-World Examples

Static Website

Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; upgrade-insecure-requests;

Website with Google Analytics & Fonts

Content-Security-Policy: default-src 'self'; script-src 'self' https://www.google-analytics.com https://ssl.google-analytics.com; style-src 'self' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https://www.google-analytics.com; connect-src 'self' https://www.google-analytics.com;

Website with YouTube Embeds

Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; frame-src https://www.youtube.com;  upgrade-insecure-requests;

E-commerce with Payment Gateway

Content-Security-Policy: default-src 'self'; script-src 'self' https://js.stripe.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; frame-src https://js.stripe.com; connect-src 'self' https://api.stripe.com;

Testing Your CSP

Report-Only Mode

Test without blocking:

Header always set Content-Security-Policy-Report-Only "default-src 'self'; report-uri /csp-report"

View Violations in Browser Console

Open DevTools (F12) → Console tab to see CSP violations.

Online Tools

Common Issues & Solutions

Inline Scripts Blocked

Problem: script-src 'self' blocks inline <script> tags.

Solution 1: Move scripts to external files.

Solution 2: Use nonces (advanced):

script-src 'self' 'nonce-random123'

Inline Styles Blocked

Problem: Inline style="" attributes blocked.

Solution: Move styles to CSS files.

Images from Other Domains

Problem: CDN images blocked.

Solution:

img-src 'self' https://cdn.example.com

Implementation

Apache (.htaccess)

<IfModule mod_headers.c>
    Header always set Content-Security-Policy "default-src 'none'; script-src 'self'; style-src 'self'; img-src data: 'self'; font-src 'self'; upgrade-insecure-requests;"
</IfModule>

Nginx

add_header Content-Security-Policy "default-src 'none'; script-src 'self'; style-src 'self'; img-src data: 'self'; font-src 'self'; upgrade-insecure-requests;" always;

PHP

header("Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self';");

CSP with Nonces (Advanced)

Generate unique nonces for each request:

<?php
$nonce = base64_encode(random_bytes(16));
header("Content-Security-Policy: script-src 'self' 'nonce-$nonce'; style-src 'self' 'nonce-$nonce';");
?>
<script nonce="<?php echo $nonce; ?>">
    console.log("This script is allowed");
</script>

Monitoring Violations

Set up Reporting Endpoint

Content-Security-Policy: default-src 'self'; report-uri https://your-domain.com/csp-report;

Example Report Handler (PHP)

<?php
$data = file_get_contents('php://input');
$report = json_decode($data, true);
file_put_contents('csp-reports.log', print_r($report, true), FILE_APPEND);
?>

Best Practices

  1. Start with Report-Only - Test before enforcing
  2. Be Specific - Don't use 'unsafe-inline' or 'unsafe-eval' unless absolutely necessary
  3. Use HTTPS - CSP works best with HTTPS
  4. Monitor Reports - Set up violation reporting
  5. Update Gradually - Add directives as needed

Security Rating Impact

Implementing CSP can improve your score on:

Related Headers

Additional Resources

User