DEV Community

Weather Clock Dash
Weather Clock Dash

Posted on

Content Security Policy in Firefox: Implementation, Debugging, and Nonce-Based CSP

Content Security Policy (CSP) is one of the most powerful web security tools available. Firefox's DevTools make it easier to implement and debug CSP. Here's a practical guide.

What CSP Does

CSP tells the browser which sources of content are legitimate for your site. If something isn't in the policy, the browser blocks it.

Without CSP: If an attacker injects <script>alert('xss')</script> into your page, the browser executes it.

With CSP: The browser checks if inline scripts are allowed. If 'unsafe-inline' isn't in the policy, the browser blocks the script before it runs.

CSP is delivered via HTTP header or meta tag:

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com
Enter fullscreen mode Exit fullscreen mode

The Core Directives

Directive Controls
default-src Fallback for unspecified directives
script-src JavaScript sources
style-src CSS sources
img-src Image sources
connect-src Fetch, XHR, WebSocket connections
font-src Font files
frame-src iframe sources
media-src Audio/video sources
object-src Plugin content (deprecated, set to 'none')
form-action Form submission targets
base-uri Allowed base href values

Common Source Values

'self'           - Same origin as the page
'none'           - Block all
'unsafe-inline'  - Allow inline scripts/styles (weakens CSP significantly)
'unsafe-eval'    - Allow eval() and similar
https:           - Any HTTPS source
https://cdn.example.com  - Specific domain
'nonce-{random}' - Allow specific inline scripts with matching nonce
'strict-dynamic' - Trust scripts that trusted scripts load
Enter fullscreen mode Exit fullscreen mode

A Practical Starter Policy

A solid baseline for a typical web app:

Content-Security-Policy: 
  default-src 'self';
  script-src 'self';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://api.yourapp.com;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';
  object-src 'none';
  upgrade-insecure-requests;
Enter fullscreen mode Exit fullscreen mode

Note: style-src 'unsafe-inline' is often necessary for styled components, CSS-in-JS libraries, and dynamically injected styles. It's weaker but often unavoidable in practice.

Debugging CSP in Firefox

Firefox's DevTools have excellent CSP violation reporting.

Console Violations

When CSP blocks something, Firefox shows a detailed error in the Console:

Content Security Policy: The page's settings blocked the loading of a resource 
at https://evil.com/tracker.js ("script-src https://cdn.yourapp.com 'self'").
Enter fullscreen mode Exit fullscreen mode

The error includes:

  • What was blocked (URL, inline script, eval)
  • Which directive blocked it
  • The current policy

This is the fastest way to identify what needs to be added to your policy.

Network Panel CSP

The Network panel shows CSP violations too — requests blocked by CSP appear as red entries. Click them to see the CSP violation details in the Security tab.

Report-Only Mode

Test CSP without breaking things:

Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report
Enter fullscreen mode Exit fullscreen mode

Firefox won't block anything but will send violation reports to your endpoint and log them to the Console. Use this to audit what your policy would break before enforcing it.

Nonce-Based CSP (Best Practice)

Instead of 'unsafe-inline', use nonces for legitimate inline scripts:

Server generates a random nonce per request:

import secrets
nonce = secrets.token_hex(16)  # 'a3f2c1...'
Enter fullscreen mode Exit fullscreen mode

Header includes the nonce:

Content-Security-Policy: script-src 'nonce-a3f2c1...' 'strict-dynamic'
Enter fullscreen mode Exit fullscreen mode

HTML uses the nonce on legitimate scripts:

<script nonce="a3f2c1...">
  // This runs — nonce matches
</script>
<script>
  // This is blocked — no nonce
</script>
Enter fullscreen mode Exit fullscreen mode

An attacker who injects <script>alert(1)</script> can't know the server-generated nonce, so their injection is blocked even with inline scripts.

'strict-dynamic' makes nonce-based CSP practical for apps using module bundlers — scripts loaded by trusted (nonce'd) scripts inherit trust.

Common CSP Issues

Google Fonts: Add https://fonts.googleapis.com to style-src and https://fonts.gstatic.com to font-src.

Google Analytics: Add https://www.google-analytics.com and https://www.googletagmanager.com to script-src and connect-src.

CDN scripts: Add the CDN domain explicitly: https://cdnjs.cloudflare.com or https://cdn.jsdelivr.net.

React/Vue hot module replacement in dev: Dev servers often need 'unsafe-eval' for HMR. Keep this only in development builds.

frame-ancestors vs X-Frame-Options

CSP's frame-ancestors directive supersedes the older X-Frame-Options header:

Content-Security-Policy: frame-ancestors 'none';      # Block all framing
Content-Security-Policy: frame-ancestors 'self';      # Allow same-origin framing
Content-Security-Policy: frame-ancestors https://allowed.example.com; # Allow specific
Enter fullscreen mode Exit fullscreen mode

'none' prevents clickjacking attacks by blocking your page from being embedded in iframes.

Firefox's CSP Visualizer

Firefox has a built-in CSP visualization tool:

  1. Open DevTools
  2. Security panel (may need to enable in the … menu)
  3. Shows the active CSP for the current page
  4. Lists each directive and its sources

This is a quick way to see the full policy without parsing headers manually.

Testing Your CSP

After deploying, test at:

  • csp-evaluator.withgoogle.com — analyzes your policy for weaknesses
  • Check all page features work as expected (login, media, forms)
  • Monitor the console for CSP violations in the first few days

CSP is incremental — start strict and add sources as needed, guided by the violation log.

Top comments (0)