Application Security
CSP Implementation
Web Security
Developer Guide
Security Headers
XSS Prevention

From Zero to Secure: Implementing CSP in Hours, Not Days

HA

Henry Addico

October 6, 2025
From Zero to Secure: Implementing CSP in Hours, Not Days

Content Security Policy implementation doesn't have to be complex or time-consuming. This guide will take you from vulnerability to protection in hours, not days, with practical tools, examples, and platform-specific instructions.

This is Part 2 of our CSP security series. If you missed it, start with Part 1: Why 50% of Web Apps Are Vulnerable to XSS to understand the business impact and risks.


Quick navigation to help you find what you need:


Understanding CSP Fundamentals and Best Practices

Before diving into implementation, let's understand how Content Security Policy works, why it's so effective, and the best practices for using it.

What CSP Does

A Content Security Policy (CSP) is an added layer of security that helps detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft, to site defacement, to malware distribution.

CSP works by enabling server administrators to reduce or eliminate the vectors through which XSS and package sniffing can occur. This is done by specifying the domains that the browser should consider to be valid sources of executable scripts, form posts, iframes and ajax calls. A CSP compatible browser will then only load resources received from or send data to those allowed domains, ignoring all other sources.

Backward Compatibility: CSP is fully backwards compatible with browsers that don't support it. Browsers that don't support CSP ignore it, functioning as usual, defaulting to the standard same-origin policy for web content.

CSP Header Types

  • Content-Security-Policy: Enforces the defined source locations within the policy on compatible browsers
  • Content-Security-Policy-Report-Only: Does not enforce the defined source locations, but only logs to the console and sends reports when the policy is violated

Core CSP Values

The policy is built up of several different directives, each can be given a space-separated list of values, of which the main ones are:

  • 'none': Won't allow loading of any resources
  • 'self': Only allow resources from the current origin
  • host: Only allow loading of resources from a specific host, with optional scheme, port, and path (e.g., example.com, *.example.com, https://*.example.com:12, https://*.example.com:12/path/to/file.js)
  • 'nonce-*': A cryptographic nonce (only used once) to allow scripts. The server must generate a unique nonce value each time it transmits a policy. It is critical to provide a nonce that cannot be guessed as bypassing a resource's policy is otherwise trivial

Best Practices

Implementing Content Security Policy involves careful consideration of best practices to strike a balance between security and functionality:

Security Principles:

  • Follow the Least Privilege Principle: Always set the default source to 'none' and only allow what is necessary
  • Disable eval() and inline scripts: Never allow 'unsafe-eval' or 'unsafe-inline' on default-* or script-* directives
  • Define specific policies: Avoid wildcards like *; be explicit about allowed sources
  • Leverage nonces or hashes for inline scripts: If inline scripts are necessary, use nonces or hashes to allowlist specific scripts

Implementation Strategy:

  • Start strict, loosen as needed: Begin with a restrictive policy and only allow what you need
  • Test in report-only mode: Use Content-Security-Policy-Report-Only to test before enforcing
  • Use environment variables or feature toggles: Manage different CSPs for development, staging, and production to avoid breaking changes

Ongoing Management:

  • Set up reporting endpoints: Configure report-uri or report-to to monitor violations
  • Iterate and monitor: CSP is not "set and forget"—review reports and update as your app evolves
  • Employ upgrade-insecure-requests: Automatically upgrade HTTP requests to HTTPS
  • Implement Subresource Integrity (SRI): Use SRI for immutable scripts to prevent tampering

Remember: CSP is not a substitute for secure development. Always follow secure coding practices such as those described in the OWASP Cross-Site Scripting Prevention Cheat Sheet, and then deploy CSP on top of that as a bonus security layer.


Essential Tools to Streamline CSP Management

Now that you understand how CSP works, these tools will dramatically reduce implementation friction, transforming what could take days into hours.

Professional CSP Management Platforms

Report URI

report-uri.com is a mature monitoring and policy-management platform focused on keeping your CSPs both effective and up-to-date, combining it with threat intelligence and other security features.

Key Features:

  • Centralized Reporting: Aggregate CSP violations across all properties
  • Analytics Dashboard: Trend analysis and violation patterns
  • Alert Systems: Continuous detection of policy drift, unexpected resource load, or suspicious changes
  • API Integration: Programmatic access to violation data
  • Compliance Support: PCI DSS compliance support
  • Multiple Tools:
    • CSP Analyser: Discover all first- and third-party resources your site uses
    • Script and Style Hasher for CSP: Generate hashes for inline scripts and styles
    • CSP Wizard: Start with Report-Only mode, block everything then discover resources, import existing policies, tweak in UI
    • CSP Builder Tool: Intuitive user interface to build a CSP
    • Real-time Monitoring/Reporting: Drift monitoring with tools like Script Watch, Data Watch, Frame Watch, Policy Watch

Best for: More useful for teams with significant traffic or complexity—if your site is simple or you don't expect many changes, you might not use all its value.

CentralCSP - Learning Through Iteration

CentralCSP makes learning and managing CSP accessible through a low entry cost and data-driven scoring covering Security, Compliance, and Best Practices. Instead of just generating policies, it delivers actionable recommendations that explain why each directive matters and how to improve. With trend tracking over time, engineers can see the impact of changes, close gaps, and continuously strengthen their CSP.

Key Features for Learning:

  • Actionable Feedback: Doesn't just tell you what's wrong—explains why and how to fix it
  • Iterative Refinement: Start with Report-Only mode, analyse violations, adjust policy, repeat
  • Real-time Violation Monitoring: See immediately how policy changes affect your application
  • Compliance Scoring: Understand how your CSP impacts security scores (BitSight, SecurityScorecard)
  • Multiple Tools in One:
    • CSP Scanner: Analyse live websites for vulnerabilities
    • CSP Evaluator: Assess policy strength and compliance
    • CSP Builder: Automated policy generation with best practices
    • Violation Reporting: Real-time monitoring dashboard

Best for: Engineers seeking a deep understanding of CSP implementation, and teams aiming to scale their security practices cost-effectively laong with compliance alignment.

Csper.io

csper.io has a higher entry price point but provides added value through paid enterprise features alongside a suite of free standalone tools. It helps teams design, test, and refine policies with real-time validation and clear guidance, making CSP adoption more approachable. While its paid tier provides advanced features for larger teams (including role management, OAuth and SAML support, full API access, and Purchase Order or contract invoicing), the free tools give engineers hands-on experience similar to CentralCSP—ideal for experimenting, learning, and tightening security practices before scaling.

Key Features:

  • Automated Policy Generation: Build new policies with a click based on previous reports
  • Continuous Monitoring: Real-time violation tracking across environments
  • Team Collaboration: Role management and OAuth/SAML support
  • Integration Support: Tiered pricing with full API access to dynamically generate projects, policies, reports and more
  • Multiple Tools in One:
    • Report Collector: Report endpoint, data aggregation, alerting and more
    • Policy Generator: Automatically generate new content security policies
    • Policy Evaluator: Evaluate existing content security policies
    • Hasher: Generate hashes for inline scripts and styles

Best for: Teams and enterprises needing OAuth and SAML support.

Web Analytics and Observability Tools with CSP Monitoring

Modern web analytics and observability platforms now include built-in CSP violation monitoring, making it easier to track security issues alongside user behavior and application performance. This is not an exhaustive list check if the web analytics and observability provide built-in CSO monitoring or create a feature request.

Datadog - CSP Reporting Integration

Datadog allows you to collect, monitor, and analyse CSP violation reports as part of your security and observability stack. You can forward CSP reports to Datadog using their HTTP API and visualize violations alongside other application and security metrics.

Best for: Teams already using Datadog for observability and security monitoring who want to centralize CSP reporting.

Honeycomb - CSP Reporting with OpenTelemetry

Honeycomb enables you to ingest and analyse CSP violation reports using OpenTelemetry Collector. This lets you correlate CSP errors with other application telemetry and observability data in Honeycomb's platform.

Best for: Teams using Honeycomb and OpenTelemetry for distributed tracing and observability who want to include CSP errors in their analysis.

GlitchTip (Sentry-Compatible)

GlitchTip is an open-source, Sentry API compatible error tracking platform that includes CSP monitoring.

Key Features:

  • Sentry API Compatible: Drop-in replacement for Sentry
  • Self-Hosted: Full data control and privacy
  • CSP Violation Tracking: Native support for CSP reports
  • Easy Deployment: Docker-based setup
  • No Usage Limits: Monitor unlimited violations

PostHog - CSP Violation Dashboard

PostHog offers a dedicated CSP violation reports dashboard template as part of their product analytics platform.

Key Features:

  • Violation Trends: Track daily violations over time with trend analysis
  • Violated Directives: Identify which CSP directives are being violated most frequently
  • Affected URLs: See which pages generate the most CSP violations
  • Recent Violations: Find the most recent violations for quick action
  • Integrated Analytics: Combine CSP monitoring with user analytics in one platform

Best for: Teams already using PostHog or looking for combined analytics and security monitoring.

Setup: Configure your CSP to send reports to PostHog's ingestion endpoint alongside your standard analytics tracking.

Raygun - CSP Violation Reporting

Raygun provides an endpoint for the browser to send CSP violation reports to, integrating CSP monitoring with their crash reporting and real user monitoring platform.

Best for: Teams using Raygun for application performance monitoring who want to add CSP violation tracking.

c/side - CSP Reporting and Security Analytics

c/side provides a modern platform for collecting, analysing, and visualising CSP violation reports. It offers real-time dashboards, alerting, and deep analytics to help you quickly identify and respond to security issues surfaced by CSP.

Best for: Teams looking for a dedicated, developer-friendly CSP reporting and analytics platform with easy setup and actionable insights.

HTTPS Reporter - CSP Reporting and Security Analytics

HTTPS Reporter provides a lightweight way to collect and analyse CSP violation reports. It offers quick setup with clear guidance for adding a report endpoint and viewing violations, helping you detect and resolve policy issues faster.

Best for: Teams wanting a low-friction, lightweight CSP reporting workflow to complement existing analytics and monitoring tools.

Online CSP Tools and Generators

CSP Builder Tools

Open-Source CSP Reporting Solutions

For teams wanting full control and no external dependencies, several open-source solutions exist:

Deployment Options:

  • Docker Compose for local/cloud hosting
  • Kubernetes for production environments
  • Integrates with existing Sentry configurations

Best for: Teams wanting Sentry-like features without the cost or data sharing concerns.

Framework-Specific Open Source Solutions

For Django (Python):

pip install django-csp-reports

django-csp-reports - A lightweight Django app for handling browser CSP violation reports.

Setup:

# settings.py
INSTALLED_APPS = [
    ...
    'cspreports',
]

# urls.py
urlpatterns = [
    path('csp-report/', include('cspreports.urls')),
]

For Node.js/Express:

Simple DIY Endpoint:

const express = require('express');
const app = express();

app.post('/csp-report', express.json({ type: 'application/csp-report' }), (req, res) => {
  const violation = req.body['csp-report'];
  console.log('CSP Violation:', {
    blockedURI: violation['blocked-uri'],
    violatedDirective: violation['violated-directive'],
    originalPolicy: violation['original-policy'],
    documentURI: violation['document-uri']
  });
  
  // Log to file, database, or monitoring service
  // logToDatabase(violation);
  
  res.status(204).send();
});

CSP Server with Elasticsearch

seek-oss/csp-server - Production-grade CSP reports server that forwards to Elasticsearch.

Features:

  • Elasticsearch integration for searchable reports
  • Scalable architecture for high-volume sites
  • Filtering and aggregation capabilities
  • Visualisation with Kibana

For Go (Golang):

Simple Handler:

package main

import (
    "encoding/json"
    "log"
    "net/http"
)

type CSPReport struct {
    BlockedURI         string `json:"blocked-uri"`
    ViolatedDirective  string `json:"violated-directive"`
    OriginalPolicy     string `json:"original-policy"`
    DocumentURI        string `json:"document-uri"`
}

type CSPReportWrapper struct {
    Report CSPReport `json:"csp-report"`
}

func cspReportHandler(w http.ResponseWriter, r *http.Request) {
    var wrapper CSPReportWrapper
    if err := json.NewDecoder(r.Body).Decode(&wrapper); err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    
    log.Printf("CSP Violation: %+v", wrapper.Report)
    // Send to logging service or database
    
    w.WriteHeader(http.StatusNoContent)
}

func main() {
    http.HandleFunc("/csp-report", cspReportHandler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

For Next.js:

API Route: pages/api/csp-report.js

export default function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ message: 'Method not allowed' });
  }

  const violation = req.body['csp-report'];
  
  console.log('CSP Violation:', {
    blocked: violation['blocked-uri'],
    directive: violation['violated-directive'],
    page: violation['document-uri']
  });

  // Send to logging service (e.g., Vercel Analytics, PostHog, CentralCSP, etc.)
  
  res.status(204).end();
}

export const config = {
  api: {
    bodyParser: {
      sizeLimit: '1mb',
    },
  },
}

For Spring Boot (Java):

@RestController
public class CSPReportController {
    
    @PostMapping(value = "/csp-report", consumes = "application/csp-report")
    public ResponseEntity<Void> handleCSPReport(@RequestBody String reportJson) {
        // Parse and log the report
        logger.info("CSP Violation: {}", reportJson);
        
        // Send to monitoring service
        // monitoringService.logViolation(reportJson);
        
        return ResponseEntity.noContent().build();
    }
}

For Gatsby:

gatsby-node.js:

exports.onCreateDevServer = ({ app }) => {
  app.post('/csp-report', express.json({ type: 'application/csp-report' }), (req, res) => {
    console.log('CSP Violation:', req.body['csp-report']);
    res.status(204).send();
  });
};

Platform-Specific Integrations

Vercel:

  • Use Next.js API routes (shown above)
  • No additional setup needed for hosting
  • Automatic HTTPS for report endpoints

Netlify:

  • Use Netlify Functions for serverless reporting
  • Create netlify/functions/csp-report.js:
exports.handler = async (event) => {
  if (event.httpMethod !== 'POST') {
    return { statusCode: 405, body: 'Method Not Allowed' };
  }
  
  const report = JSON.parse(event.body)['csp-report'];
  console.log('CSP Violation:', report);
  
  return { statusCode: 204, body: '' };
};

Recommended Tool Workflow

For New Projects:

  1. Start early with CSP Generator: Auto-generate initial policy
  2. Validate with CSP Evaluator: Check for security weaknesses
  3. Test with CSP Tester: Verify application compatibility
  4. Set up reporting: Choose tools based on your stack or budget
  5. Deploy with Report-Only: Monitor real-world behavior
  6. Enforce and Monitor: Switch to enforcement mode with continuous monitoring

For Existing Applications:

  1. Use report only mode to scan or CSP Evaluator: Assess current security posture on a small/low volume site
  2. Generate with a Builder: Create policies based on actual usage
  3. Set up reporting endpoint: Choose from options above
  4. Test Gradually: Use Report-Only mode extensively (1-2 weeks)
  5. Refine Iteratively: Adjust based on violation reports and actionable advice
  6. Scale monitoring: Scale to other site

Quick Start: 5-Minute CSP Protection

For immediate basic protection following the least privilege principle:

Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; connect-src 'self'; frame-ancestors 'none';

This policy starts with maximum restrictions (default-src 'none') and only allows what's explicitly needed.

What this policy does:

  • Blocks all resources by default (default-src 'none')
  • Allows scripts only from your own domain (script-src 'self')
  • Allows styles only from your domain (style-src 'self')
  • Allows images only from your domain (img-src 'self')
  • Allows fonts only from your domain (font-src 'self')
  • Allows network connections only to your domain (connect-src 'self')
  • Blocks your site from being framed (frame-ancestors 'none')

Note: If you use inline styles or external CDNs, you'll need to adjust this policy (covered in the detailed implementation section).

You can find additional examples in the Content Security Policy (CSP) Quick Reference Guide. Please note that these resources were created at a specific point in time — use them as a reference or starting point, and make sure to check for updates, validate configurations, and thoroughly test before applying them.


The Complete Implementation Process

Step 1: Audit Your Dependencies (15-30 minutes)

Before configuring CSP, you need to understand what external resources your application uses.

Create a resource inventory:

  1. CDNs and External Scripts

    • Google Analytics, Google Fonts, Font Awesome
    • JavaScript libraries from CDNs (jQuery, React, etc.)
    • Payment processors (Stripe, PayPal)
    • Social media widgets
  2. Media and Assets

    • Image hosting services (Cloudinary, AWS S3)
    • Video platforms (YouTube, Vimeo)
    • External stylesheets
  3. APIs and Data Sources

    • REST APIs, GraphQL endpoints
    • Third-party data services
    • WebSocket connections

Use browser tools to discover resources:

// Run this in your browser console to see all loaded resources
Array.from(document.querySelectorAll('script[src], link[href], img[src]'))
  .map(el => new URL(el.src || el.href).origin)
  .filter((origin, index, arr) => arr.indexOf(origin) === index)
  .sort();

Step 2: Choose Your CSP Strategy

Based on the OWASP CSP Cheat Sheet, there are two main approaches:

Option A: Strict CSP (Recommended)

Best for: New applications or those you can modify

Benefits:

  • Highest security level
  • Future-proof against new attack vectors
  • Easier to maintain long-term

Requirements:

  • Ability to add nonces or hashes to scripts
  • Remove or refactor inline event handlers
  • Some development workflow changes

Option B: Allowlist-based CSP

Best for: Legacy applications or third-party heavy sites

Benefits:

  • Easier initial implementation
  • Works with existing inline scripts
  • No code changes required

Limitations:

  • More vulnerable to bypasses
  • Requires ongoing maintenance as dependencies change

Step 3: Draft Your CSP Policy

For Strict CSP (Recommended Approach)

Nonce-based Strict Policy:

Content-Security-Policy: 
  script-src 'nonce-{RANDOM}' 'strict-dynamic'; 
  object-src 'none'; 
  base-uri 'none';

Hash-based Strict Policy:

Content-Security-Policy: 
  script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic'; 
  object-src 'none'; 
  base-uri 'none';

For Allowlist-based CSP

E-commerce Site with Common Services:

Content-Security-Policy: 
  default-src 'self'; 
  script-src 'self' https://js.stripe.com https://www.googletagmanager.com; 
  style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; 
  font-src 'self' https://fonts.gstatic.com; 
  img-src 'self' data: https: *.stripe.com; 
  connect-src 'self' https://api.stripe.com https://www.google-analytics.com;
  frame-ancestors 'none';

Marketing Site with Analytics:

Content-Security-Policy: 
  default-src 'self'; 
  script-src 'self' https://www.googletagmanager.com https://www.google-analytics.com; 
  style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; 
  font-src 'self' https://fonts.gstatic.com; 
  img-src 'self' data: https:; 
  connect-src 'self' https://www.google-analytics.com;
  frame-ancestors 'none';

SaaS Application:

Content-Security-Policy: 
  default-src 'self'; 
  script-src 'self'; 
  style-src 'self' 'unsafe-inline'; 
  img-src 'self' data: https:; 
  connect-src 'self' wss: https:; 
  font-src 'self';
  frame-ancestors 'none';

Step 4: Platform-Specific Implementation

Netlify (5-10 minutes, Beginner)

Create a _headers file in your site's publish directory:

/*
  Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none';
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin
  Permissions-Policy: camera=(), microphone=(), geolocation=()

Watch: Netlify Headers Configuration Tutorial

Vercel (5-10 minutes, Beginner)

Add to your vercel.json file:

{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "Content-Security-Policy",
          "value": "default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none';"
        },
        {
          "key": "X-Frame-Options",
          "value": "DENY"
        },
        {
          "key": "X-Content-Type-Options",
          "value": "nosniff"
        },
        {
          "key": "Referrer-Policy",
          "value": "strict-origin-when-cross-origin"
        }
      ]
    }
  ]
}

AWS Amplify (10-15 minutes, Intermediate)

Create a customHttp.yml file in your project root or configure in the Amplify Console:

customHeaders:
  - pattern: '**'
    headers:
      - key: 'Content-Security-Policy'
        value: "default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none';"
      - key: 'X-Frame-Options'
        value: 'DENY'
      - key: 'X-Content-Type-Options'
        value: 'nosniff'
      - key: 'Referrer-Policy'
        value: 'strict-origin-when-cross-origin'

Or via the AWS Console:

  1. Go to Amplify Console → Your App → App settings → Custom headers
  2. Add headers configuration
  3. Deploy changes

Cloudflare Pages (10-15 minutes, Intermediate)

Create a _headers file:

/*
  Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none';
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin

Firebase Hosting (10-15 minutes, Intermediate)

Add to your firebase.json:

{
  "hosting": {
    "headers": [
      {
        "source": "**",
        "headers": [
          {
            "key": "Content-Security-Policy",
            "value": "default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none';"
          },
          {
            "key": "X-Frame-Options",
            "value": "DENY"
          },
          {
            "key": "X-Content-Type-Options",
            "value": "nosniff"
          }
        ]
      }
    ]
  }
}

Azure Static Web Apps (10-20 minutes, Intermediate)

Create a staticwebapp.config.json:

{
  "globalHeaders": {
    "Content-Security-Policy": "default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none';",
    "X-Frame-Options": "DENY",
    "X-Content-Type-Options": "nosniff",
    "Referrer-Policy": "strict-origin-when-cross-origin"
  }
}

Digital Ocean App Platform (15-30 minutes, Advanced)

Currently requires using meta tags in your HTML or upgrading to a more flexible plan:

<meta http-equiv="Content-Security-Policy" 
      content="default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data: https:; font-src 'self'; connect-src 'self';">

Note: Meta tag CSP cannot set frame-ancestors directive.

Step 5: Test Your Implementation (15-30 minutes)

Use Content-Security-Policy-Report-Only First

Before enforcing your policy, test it using the report-only mode:

Content-Security-Policy-Report-Only: your-policy-here; report-uri /csp-report-endpoint

This logs violations without blocking resources, allowing you to identify issues.

Browser Testing

  1. Open Developer Tools → Console tab
  2. Load your application and navigate through key pages
  3. Look for CSP violations - they'll appear as console errors
  4. Test critical functionality - forms, payments, user interactions

Automated Testing Tools

Online Scanners:

Browser Extensions: There are browser extensions but I have intentonaly not included them due to lack of updates or reviews.

Common Issues and Fixes

Problem: Inline scripts blocked

Refused to execute inline script because it violates CSP directive 'script-src'

Solution: Move scripts to external files or use nonces/hashes

Problem: Third-party widgets not loading

Refused to load script from 'https://widget.example.com' because it violates CSP

Solution: Add the domain to your script-src directive

Problem: Images from user uploads not displaying

Refused to load image from 'https://user-uploads.com' because it violates CSP

Solution: Add the upload domain to img-src or use https: for all HTTPS images

Step 6: Monitor and Maintain

Set Up Violation Reporting

For production monitoring, implement CSP reporting:

Content-Security-Policy: your-policy-here; report-uri https://your-domain.com/csp-report

Simple Node.js Report Endpoint:

app.post('/csp-report', express.json({ type: 'application/csp-report' }), (req, res) => {
  console.log('CSP Violation:', req.body);
  // Log to your monitoring system (CentralCSP, PostHog, GlitchTip, etc.)
  res.status(204).send();
});

Regular Maintenance Tasks

Monthly Reviews:

  • Check for new CSP violations in logs
  • Review and update third-party domains
  • Test policy after major application changes

Quarterly Assessments:

  • Run security scans on updated policy
  • Review and tighten overly permissive directives
  • Update CSP as application evolves

Common Implementation Challenges and Solutions

Google Tag Manager Integration

By default, Google Tag Manager provides inline scripts that need to be added to the page. However, these scripts will not work when using a CSP, as they will be disabled. The best approach is to use the npm module react-gtm-module, which will include the Google Tag Manager code in a way that complies with CSP.

This can be achieved by using the following code snippet in your _app.js file:

import TagManager from "react-gtm-module"
import {useEffect} from "react";
 
const tagManagerArgs = {
    gtmId: "GTM-NHFQHGV",
}
 
export default function App({ Component, pageProps }) {
    useEffect(() => {
        TagManager.initialize(tagManagerArgs)
    }, )
 
    return <Component {...pageProps} />;
}

Server Redirects and Form Actions

When redirecting, the CSP checks the entire chain of sources, but browsers have differences in behavior for form-action redirects:

  • Chrome/Safari: Consider redirects when submitting forms potentially dangerous, since sensitive user data can be redirected to an attacker's domain. They block redirection if host-source (domain) not allowed in form-actions are in the redirect chain.
  • Firefox: Believes that server redirects are under the control of the page owner protected by CSP. During a redirect, it allows form submission even to third-party domains.

Practical Example: If your service redirects customers from a.b.com to c.b.com and you have a CSP of:

Content-Security-Policy: form-action 'self' https:;

Firefox would allow the form to submit and redirect, but Chrome/Safari will not unless you have:

Content-Security-Policy: form-action 'self' https: c.b.com;

Best Practice: Always ensure any redirect domains coming from your server are added to the CSP.

Browser Compatibility Considerations

Be aware that not all browsers are fully compatible with CSP policies. Test your application across different browsers to ensure consistent behavior and adapt the policy if needed. Modern browsers have excellent CSP support, but legacy browsers may require fallback strategies.


Advanced Considerations for Scaling Startups

As highlighted in LinkedIn's security engineering journey, implementing security practices early becomes exponentially more difficult as your team and application grow.

Key considerations for growing teams:

  1. Development Workflow Integration: Incorporate CSP testing into your CI/CD pipeline
  2. Team Training: Ensure all developers understand CSP implications for new features
  3. Policy Management: Use configuration management to keep CSP consistent across environments
  4. Monitoring Infrastructure: Implement proper logging and alerting for CSP violations
  5. Security Review Process: Include CSP impact in feature review checklists

Troubleshooting Common Issues

CSP Policy Too Restrictive

Symptoms: Application features breaking, resources not loading

Solution: Temporarily use Content-Security-Policy-Report-Only to identify needed permissions

Policy Too Permissive

Symptoms: CSP evaluator tools showing warnings

Solution: Gradually tighten restrictions, starting with default-src 'none' and adding only necessary permissions

Third-party Integrations Breaking

Symptoms: Analytics, chat widgets, or payment forms not working

Solution: Check integration documentation for required CSP directives

Development vs Production Differences

Symptoms: CSP works locally but fails in production

Solution: Ensure your CSP accounts for production CDNs, monitoring tools, and deployment differences


Next Steps: Beyond CSP

Implementing CSP is an excellent start to your application security journey. Consider these additional security measures:

Immediate Next Steps

  1. Implement other security headers: Strict-Transport-Security, X-Content-Type-Options
  2. Enable Subresource Integrity (SRI) for third-party resources
  3. Review and implement HTTPS everywhere

Strategic Security Planning

  1. Threat Modeling: Use the NCSC threat modelling guide to identify broader security risks
  2. Security Testing: Integrate security testing into your development workflow
  3. Incident Response Planning: Prepare for security incidents before they happen

Professional Security Assessment

For comprehensive security evaluation, consider a professional security assessment. This is particularly valuable for:

  • Applications handling sensitive data
  • Growing startups preparing for compliance requirements
  • Teams wanting expert validation of their security posture

Conclusion

Content Security Policy implementation doesn't have to be daunting. With the right approach and tools, you can secure your application in hours, not days:

  1. Understand the fundamentals - CSP mechanics, headers, and best practices
  2. Use the right tools - Pick a tool chain that suits your team and organisation
  3. Start with basic protection using the quick-start policy
  4. Audit your dependencies to understand your requirements
  5. Choose the appropriate CSP strategy for your application
  6. Implement platform-specific configuration using our guides
  7. Test thoroughly with Report-Only mode before enforcing
  8. Monitor and maintain your policy over time

The time investment is minimal compared to the protection gained. Your users, your data, and your business reputation are worth the effort.

Take action today: Pick your platform, follow the configuration steps, and join the 50% of applications that properly protect their users against XSS attacks.


Key Resources


About This Series: