CentralCSP

Main menu

All articles

Next Article

Stay safe, no more unsafe-inline

Get started with CSP

Tuesday, December 3, 2024

5 min read

Theotime Quere

Theotime Quere

Learn how to implement Content Security Policy step by step. From choosing the right implementation method for your technology stack to handling inline scripts and styles with nonces.

Understanding CSP Implementation

Before implementing CSP, you need to understand your technology stack and how it handles scripts and styles. Different frameworks and technologies require different approaches.

1. Choose Your Implementation Method

CSP can be implemented through HTTP headers or meta tags. HTTP headers are recommended for better security:

Learn more about implementation methods

Common Server Configurations

Here's how to implement CSP headers in different server environments. Each configuration adds the basic 'default-src self' policy, which you'll need to customize based on your needs:

Nginx configuration

server {
  add_header Content-Security-Policy 'default-src 'self';' always;
}

The 'always' directive in Nginx ensures the header is sent with every response, including error pages. This is important for maintaining consistent security across your site.

Apache (.htaccess)

Header set Content-Security-Policy 'default-src 'self';'

For Apache servers, you can place this in your .htaccess file or in the main server configuration. Make sure mod_headers is enabled in your Apache configuration.

Express.js

app.use((req, res, next) => {
  res.setHeader('Content-Security-Policy', 'default-src 'self';');
  next();
});

In Express.js, this middleware ensures the CSP header is added to every response. You can also use the helmet middleware package for more comprehensive security headers.

2. Analyze Your Current Setup

Before implementing CSP, analyze how your application uses scripts and styles:

  • Check for inline scripts and styles in your HTML

  • Identify third-party resources your site depends on

  • Review framework-specific script injection

3. Understanding Nonces

Nonces are crucial for securing inline scripts and styles. A nonce (number used once) is a unique, random value generated for each page load that helps the browser identify legitimate inline scripts:

Important Implementation Consideration

Setting up nonces can be challenging depending on your technology stack. If you're using a web server like Nginx to set CSP headers and a separate framework to build pages, you need to carefully plan how to share the nonce between your CSP header and page content. Ensure your architecture allows the same nonce to be available both when setting the CSP header and when rendering the page content.

Example of nonce generation in Node.js

const crypto = require('crypto');
const nonce = crypto.randomBytes(16).toString('base64');

The nonce should be cryptographically random and at least 128 bits long when base64 encoded. Never reuse nonces across different page loads, as this would defeat their security purpose.

How Nonces Work

A nonce is a one-time-use cryptographic number that allows specific inline scripts to execute. The same nonce must be present in both your CSP header and script tag. The browser will only execute inline scripts whose nonce matches the one in the CSP header.

Example of nonce usage

// In your CSP header
Content-Security-Policy: script-src 'nonce-random123';

// In your HTML
<script nonce='random123'>
// This script will execute
console.log('Hello World');
</script>

4. Framework-Specific Setup

Different frameworks require specific approaches to CSP implementation. Here's how to handle CSP in popular frameworks while maintaining security and functionality:

Next.js Implementation

There are multiple ways to implement CSP in Next.js, depending on your specific needs and architecture:

  • Using middleware for dynamic CSP generation

  • Configuring headers in next.config.js for static CSP

  • Custom server implementation for full control

Each approach has its own tradeoffs in terms of flexibility, complexity, and maintenance. The best choice depends on your specific requirements.

Learn how to setup nonces with Next.js

Here's a basic example using _document.js, but check the detailed guide for more comprehensive implementations:

Basic Next.js CSP setup example

import Document, { Html, Head, Main, NextScript } from 'next/document'

class MyDocument extends Document {
render() {
  const nonce = 'random123' // This is just an example - see full guide for proper implementation
  
  return (
    <Html>
      <Head nonce={nonce} />
      <body>
        <Main />
        <NextScript nonce={nonce} />
      </body>
    </Html>
  )
}
}

Styled-Components Configuration

When using styled-components, ensure you're using the server-side rendering setup with nonces to maintain CSP compliance. This allows dynamic styles while keeping security intact.

5. Handling Inline Scripts and Styles

Inline scripts and styles pose a particular challenge for CSP implementation. Here are three comprehensive approaches to handle them securely:

  • 1. Use Nonces

    Generate and apply nonces to necessary inline elements. This is the most flexible approach as it allows you to keep inline scripts while maintaining security. Remember to generate a new nonce for each page load.

  • 2. Move to External Files

    Extract inline scripts and styles to external files. This is the cleanest approach and makes your CSP simpler to maintain. It also improves caching and code organization.

  • 3. Calculate Hashes

    Use hashes for static inline scripts that can't be moved. This works well for scripts that never change, but requires updating the CSP header if the script content changes.

Avoid unsafe-inline

Using 'unsafe-inline' defeats much of CSP's security benefits. Always prefer nonces or hashes over unsafe-inline.

Learn more about unsafe-inline risks

6. Testing Your Implementation

Before enforcing CSP, use Report-Only mode to identify potential issues:

Learn how to set up CSP reporting

Example of Report-Only CSP

Content-Security-Policy-Report-Only: default-src 'self';
  script-src 'self' 'nonce-random123';
  style-src 'self' 'nonce-random123';
  report-uri https://report.centralcsp.com/your-endpoint;

During development, you can also monitor CSP violations directly in your browser's developer tools:

CSP violations shown in browser console

For a more detailed analysis, you can use the Issues tab in Chrome DevTools to inspect CSP violations:

CSP issues in Chrome DevTools Issues tab

Clicking the 'Element' link in the Issues tab will highlight the exact HTML element that triggered the CSP violation, making it easy to identify problematic code:

CSP violation element highlight in DevTools

In this example, the CSP violation occurred because a script tag was missing the required nonce attribute. The browser blocked its execution since it didn't match our CSP policy requiring nonces:

Development Tools

While browser developer tools are great for debugging during development, they don't replace proper CSP reporting endpoints in production environments.

Best Practices

  • Start with Report-Only mode to identify potential issues

  • Use nonces instead of unsafe-inline whenever possible

  • Keep external scripts and styles on trusted domains

  • Regularly review and update your CSP as your application evolves

Conclusion

Implementing CSP requires careful planning and understanding of your application's architecture. Start with analysis, implement gradually using Report-Only mode, and continuously monitor and adjust your policy as needed.

Continue Reading

How to setup my reporting endpoint?

Learn how to properly setup your reporting endpoint using report-uri & CentralCSP

2024-11-22

3 min read

Theotime Quere

Theotime Quere

Read more →

Stay safe, no more unsafe-inline

Learn more about unsafe-inline and how to properly setup your CSP to avoid using it.

2024-12-03

5 min read

Theotime Quere

Theotime Quere

Read more →

Docs

CSP ScannerCSP EvaluatorReporting Endpoint

Contact


CentralSaaS © 2025