opdeck / blog / check-content-security-policy-headers

How to Check Content Security Policy Headers with OpDeck's Scanner

May 15, 2026 / OpDeck Team
Content Security PolicyWeb SecurityXSS ProtectionOpDeck ScannerCSP Headers

If you're trying to check Content Security Policy headers on your website, you're already thinking about security the right way. CSP headers are one of the most effective defenses against cross-site scripting (XSS) attacks, clickjacking, and data injection — but only if they're correctly configured and actually present. This guide walks you through exactly how to check Content Security Policy headers, what to look for, how to interpret the results, and how to fix common misconfigurations.


What Is a Content Security Policy Header?

A Content Security Policy (CSP) is an HTTP response header that tells browsers which content sources are trusted for your web page. When a browser loads your site, it checks the CSP header and blocks any resources — scripts, stylesheets, images, fonts, iframes — that don't match the policy you've defined.

Here's a simple example of what a CSP header looks like in an HTTP response:

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src *;

Breaking that down:

  • default-src 'self' — By default, only load resources from the same origin
  • script-src 'self' https://cdn.example.com — Scripts can only come from your domain or that specific CDN
  • style-src 'self' 'unsafe-inline' — Styles can come from your domain or be inline (though unsafe-inline weakens protection)
  • img-src * — Images can be loaded from anywhere

Without a CSP header, browsers apply no restrictions on resource loading, leaving your users vulnerable to injected malicious scripts.


Why Checking Your CSP Header Matters

Many developers assume that because they set a CSP header during initial deployment, it's still there and working correctly. That assumption can be dangerous. Headers can be:

  • Accidentally removed during server migrations or deployments
  • Overridden by CDN configurations or reverse proxies
  • Too permissive due to rushed debugging sessions where unsafe-inline or unsafe-eval were added and never removed
  • Broken by third-party integrations that require additional sources you forgot to whitelist

Regularly checking your CSP header ensures your security posture hasn't quietly degraded. It also helps you catch overly broad policies that give a false sense of security.


How to Check Content Security Policy Headers: Multiple Methods

There are several ways to check Content Security Policy headers, ranging from browser developer tools to command-line utilities to dedicated security scanners. Each approach has its use case.

Method 1: Using Browser Developer Tools

The quickest way to check a CSP header for any website is through your browser's built-in developer tools.

Steps for Chrome or Firefox:

  1. Open the website you want to inspect
  2. Press F12 (or Ctrl+Shift+I on Windows, Cmd+Option+I on Mac) to open DevTools
  3. Click on the Network tab
  4. Reload the page (F5 or Cmd+R)
  5. Click on the first document request (usually the HTML file at the top of the list)
  6. Select the Headers tab in the right panel
  7. Scroll down to the Response Headers section and look for content-security-policy

If you see the header, you'll get its full value. If it's absent, that's a red flag worth addressing immediately.

What to look for:

  • Is the header present at all?
  • Does it use Content-Security-Policy (enforced) or Content-Security-Policy-Report-Only (monitoring mode only)?
  • Are there any obviously dangerous directives like script-src * or default-src *?

Method 2: Using cURL from the Command Line

For developers comfortable with the terminal, curl is a fast way to fetch and inspect headers directly.

curl -I https://yourdomain.com

The -I flag sends a HEAD request and returns only the headers. Look for the content-security-policy line in the output.

Example output:

HTTP/2 200
content-type: text/html; charset=UTF-8
x-frame-options: SAMEORIGIN
content-security-policy: default-src 'self'; script-src 'self' 'nonce-abc123'; object-src 'none'
x-content-type-options: nosniff
strict-transport-security: max-age=31536000; includeSubDomains

If you want to filter just the CSP line:

curl -sI https://yourdomain.com | grep -i content-security-policy

This returns nothing if no CSP header is set — which itself tells you something important.

You can also use curl with the -v flag for verbose output, which shows the full request/response cycle including all headers:

curl -v https://yourdomain.com 2>&1 | grep -i "content-security"

Method 3: Using Python for Automated Checks

If you're auditing multiple pages or want to integrate CSP checking into a CI/CD pipeline, Python makes it straightforward:

import requests

def check_csp(url):
    try:
        response = requests.get(url, timeout=10)
        headers = response.headers
        
        csp = headers.get('Content-Security-Policy')
        csp_report_only = headers.get('Content-Security-Policy-Report-Only')
        
        if csp:
            print(f"[ENFORCED CSP FOUND]\n{csp}\n")
        elif csp_report_only:
            print(f"[REPORT-ONLY CSP FOUND — Not enforced]\n{csp_report_only}\n")
        else:
            print("[WARNING] No Content-Security-Policy header found.")
    except requests.RequestException as e:
        print(f"Error fetching {url}: {e}")

check_csp("https://yourdomain.com")

You can extend this to loop through a list of URLs from a sitemap, check subdomains, or log results to a file for periodic audits.

Method 4: Using OpDeck's Vulnerability Scanner

The most thorough and beginner-friendly way to check Content Security Policy headers is with a dedicated security scanner. The Vulnerability Scanner from OpDeck audits your site's security headers in seconds, including your CSP configuration.

Here's what makes it particularly useful:

It checks more than just presence. The scanner doesn't just tell you whether a CSP header exists — it analyzes the policy for common weaknesses like:

  • Use of unsafe-inline in script-src
  • Wildcard (*) sources that defeat the purpose of CSP
  • Missing object-src directives (a common XSS vector via Flash or plugins)
  • Absence of base-uri restrictions
  • Missing form-action controls

It checks all the related security headers together. CSP is part of a broader set of HTTP security headers. The scanner simultaneously checks for:

  • X-Frame-Options (clickjacking protection)
  • X-Content-Type-Options (MIME sniffing protection)
  • Strict-Transport-Security (HTTPS enforcement)
  • Referrer-Policy
  • Permissions-Policy

How to use it:

  1. Go to the Vulnerability Scanner on OpDeck
  2. Enter your website URL
  3. Click Scan
  4. Review the results — each header is flagged as present, missing, or misconfigured with a clear explanation

This is especially useful if you're not comfortable parsing raw header output or if you want a shareable report for a client or security review.


Understanding CSP Directives: What Each One Controls

Once you've retrieved your CSP header, you need to know how to read it. Here's a reference for the most important directives:

Source Directives

Directive What It Controls
default-src Fallback for all resource types not explicitly specified
script-src JavaScript files and inline scripts
style-src CSS stylesheets and inline styles
img-src Images (including data URIs)
font-src Web fonts
connect-src Fetch, XHR, WebSocket, EventSource connections
media-src Audio and video elements
object-src <object>, <embed>, <applet> elements
frame-src Iframes and frames
worker-src Web Workers and Service Workers
manifest-src Web app manifests

Navigation and Form Directives

Directive What It Controls
base-uri Restricts URLs in <base> elements
form-action Restricts where forms can submit data
frame-ancestors Controls which pages can embed your page in a frame
navigate-to Restricts navigation targets (experimental)

Source Values

Value Meaning
'self' Same origin only
'none' No sources allowed
'unsafe-inline' Allows inline scripts/styles (weakens security)
'unsafe-eval' Allows eval() and similar (weakens security)
'nonce-{value}' Allows specific inline scripts with matching nonce
'sha256-{hash}' Allows scripts matching a specific hash
https: Any HTTPS source
* Any source (avoid this)

Common CSP Misconfigurations to Watch For

When you check Content Security Policy headers, these are the most frequently encountered problems:

1. Missing CSP Header Entirely

This is the most common finding. No CSP means no protection. Browsers will load any resource from any origin without restriction.

Fix: Add a CSP header at the server or CDN level. Start with a strict base and loosen as needed.

2. Using unsafe-inline in script-src

Content-Security-Policy: script-src 'self' 'unsafe-inline';

This allows any inline <script> tag to execute, which largely defeats the purpose of CSP for XSS protection. Attackers who can inject HTML can still run scripts.

Fix: Use nonces or hashes instead:

Content-Security-Policy: script-src 'self' 'nonce-{random_value}';

Then add the matching nonce to each legitimate <script> tag:

<script nonce="random_value">
  // your code here
</script>

3. Wildcard in script-src

Content-Security-Policy: script-src *;

This allows scripts from any domain — functionally no protection at all.

4. Missing object-src 'none'

If object-src isn't explicitly set and default-src is permissive, browsers can load Flash and plugin content, which has historically been a major attack vector.

Fix: Always include object-src 'none' unless you specifically need plugin content.

5. Report-Only Mode Left in Production

Content-Security-Policy-Report-Only: default-src 'self';

Report-only mode is great for testing, but it doesn't actually block anything. It only sends violation reports to a configured endpoint. If you're running in report-only mode in production and forgot about it, you have zero enforcement.

6. Allowing data: URIs in script-src

Content-Security-Policy: script-src 'self' data:;

The data: scheme can be used to execute arbitrary scripts and should never appear in script-src.


How to Set CSP Headers on Different Servers

Once you've identified gaps, here's how to add or fix CSP headers on common server configurations:

Apache (.htaccess or httpd.conf)

Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self';"

Nginx (nginx.conf)

add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self';" always;

Node.js / Express

Using the helmet package (highly recommended):

const helmet = require('helmet');

app.use(
  helmet.contentSecurityPolicy({
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'"],
      styleSrc: ["'self'"],
      imgSrc: ["'self'", "data:"],
      fontSrc: ["'self'"],
      objectSrc: ["'none'"],
      baseUri: ["'self'"],
      formAction: ["'self'"],
    },
  })
);

Cloudflare Workers

If your site runs behind Cloudflare, you can inject headers via a Worker:

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  const response = await fetch(request);
  const newHeaders = new Headers(response.headers);
  
  newHeaders.set(
    'Content-Security-Policy',
    "default-src 'self'; script-src 'self'; object-src 'none';"
  );
  
  return new Response(response.body, {
    status: response.status,
    headers: newHeaders,
  });
}

Building a Habit: Regular CSP Audits

Checking your CSP header once isn't enough. Security headers need ongoing attention because:

  • Third-party scripts change — A new analytics tag or chat widget may require CSP updates
  • Deployments can reset headers — Especially on platforms that regenerate server configs
  • New attack techniques emerge — What was a secure policy two years ago may have known bypasses today

Set up a recurring audit schedule — monthly at minimum, weekly for high-traffic or sensitive applications. You can automate this with a cron job running the Python script from earlier, or use the Vulnerability Scanner on OpDeck as part of your regular maintenance routine.


Conclusion

Knowing how to check Content Security Policy headers is a fundamental skill for anyone responsible for web security. Whether you use browser DevTools for a quick spot-check, curl for command-line inspection, a Python script for automated auditing, or a full-featured scanner, the important thing is that you're checking — and acting on what you find.

The most common outcome when you first audit a site is discovering either a missing CSP header or one that's been weakened with unsafe-inline or wildcard sources. Both are fixable, and the fixes are well worth the effort given how much damage an XSS attack can cause.

For a fast, comprehensive audit that goes beyond just CSP headers and covers your full security header posture, try the Vulnerability Scanner at OpDeck. It gives you a clear picture of where your site stands and what needs attention — no terminal required.