Content-Security-Policy

Cross-site scripting and data injection attacks exploit uncontrolled resource loading. The HTTP Content-Security-Policy response header defends against these threats by controlling which resources a browser is allowed to load for a given page.

Usage

The Content-Security-Policy (CSP) header gives site administrators fine-grained control over resource loading. By declaring a policy, the server instructs the browser to only load scripts, styles, images, fonts, and other resources from approved sources. Any resource not matching the policy is blocked, and the browser reports the violation.

A policy consists of one or more directives separated by semicolons. Each directive names a resource type and lists the sources allowed for the resource type.

Content-Security-Policy: <directive> <source>; <directive>
  <source>

Deploying a new policy in report-only mode first is a common practice. The Content-Security-Policy-Report-Only header applies the same syntax but logs violations without blocking resources, allowing administrators to test a policy before enforcement.

Fetch directives

Fetch directives control the locations from which specific resource types load.

default-src

The default-src directive serves as the fallback for all other fetch directives. When a specific fetch directive is absent, the browser falls back to default-src.

Content-Security-Policy: default-src 'self'

script-src

The script-src directive restricts sources for JavaScript execution. Nonce-based and hash-based allowlists offer stronger protection than host-based rules.

script-src-elem

The script-src-elem directive applies to <script> elements specifically, overriding script-src for element contexts while leaving inline event handlers governed by script-src-attr.

script-src-attr

The script-src-attr directive governs inline event handlers like onclick and onload, separate from <script> element loading.

style-src

The style-src directive specifies valid sources for CSS stylesheets, including inline styles and external stylesheet links.

style-src-elem

The style-src-elem directive applies to <style> elements and <link rel="stylesheet"> tags, overriding style-src for those contexts.

style-src-attr

The style-src-attr directive governs inline styles applied directly to DOM elements through the style attribute.

img-src

The img-src directive specifies valid sources for images and favicons.

connect-src

The connect-src directive restricts URLs accessible through script interfaces including fetch(), XMLHttpRequest, WebSocket, and EventSource.

font-src

The font-src directive specifies valid sources for fonts loaded through @font-face.

frame-src

The frame-src directive specifies valid sources for nested browsing contexts loaded by <frame> and <iframe> elements.

media-src

The media-src directive specifies valid sources for <audio>, <video>, and <track> elements.

object-src

The object-src directive restricts sources for <object> and <embed> elements (<applet> is a legacy element removed from the HTML specification). Setting this to 'none' is recommended since these elements are rarely needed.

child-src

The child-src directive defines allowed sources for web workers and nested browsing contexts. The more specific frame-src and worker-src directives override child-src when present.

worker-src

The worker-src directive applies to Worker, SharedWorker, and ServiceWorker scripts.

manifest-src

The manifest-src directive specifies valid sources for web application manifest files.

Document directives

Document directives govern properties of the document environment.

base-uri

The base-uri directive restricts URLs allowed in the <base> element, preventing attackers from changing the base URL for relative links.

sandbox

The sandbox directive applies restrictions to the page similar to the <iframe> sandbox attribute. Sandboxed pages lose access to scripts, forms, popups, and other features unless explicitly re-enabled through sandbox flags.

Navigation directives control where users and forms send requests.

form-action

The form-action directive restricts URLs accepted as form submission targets.

frame-ancestors

The frame-ancestors directive specifies valid parents allowed to embed the page using <frame>, <iframe>, <object>, or <embed> (the <applet> element has been removed from the HTML specification). Setting frame-ancestors 'none' replaces the X-Frame-Options: DENY header.

The navigate-to directive was proposed to restrict URLs the document is allowed to navigate to through any mechanism. This directive was removed from the CSP Level 3 specification and was never shipped in any production browser.

Reporting directives

Reporting directives control violation reporting behavior.

report-to

The report-to directive specifies a reporting group name defined by the Reporting-Endpoints header. Violation reports are sent to the endpoint associated with the named group.

report-uri

The report-uri directive sends violation reports to a specified URL. This directive is being replaced by report-to but remains widely deployed for backward compatibility.

Other directives

upgrade-insecure-requests

The upgrade-insecure-requests directive instructs the browser to treat all HTTP URLs on the page as HTTPS. This is valuable during migration from HTTP to HTTPS when many resources still reference insecure URLs.

require-trusted-types-for

The require-trusted-types-for directive enforces Trusted Types policies for DOM XSS injection sinks, requiring typed objects instead of strings.

trusted-types

The trusted-types directive specifies an allowlist of Trusted Types policy names, restricting which policies the page is allowed to create.

Source values

Directives accept source expressions defining where resources load from.

'self'

Matches the current origin (same scheme, host, and port). Does not include subdomains.

'none'

Blocks all sources for the directive. No resources of the specified type load.

'unsafe-inline'

Allows inline <script> and <style> elements as well as inline event handlers. Using nonce or hash sources is preferred over 'unsafe-inline'.

'unsafe-eval'

Allows dynamic code evaluation through eval(), Function(), and similar constructs.

'unsafe-hashes'

Allows specific inline event handlers identified by their hash, without enabling all inline scripts.

'strict-dynamic'

Extends trust to scripts loaded by an already-trusted script. Combined with nonce-based policies, this eliminates the need to allowlist every script host individually.

'nonce-*'

A cryptographic nonce (number used once) generated by the server for each response. The nonce value in the policy matches the nonce attribute on <script> or <style> elements. The server generates a fresh nonce per response.

Content-Security-Policy: script-src 'nonce-abc123'

'sha256-*', 'sha384-*', 'sha512-*'

A hash of the inline script or style contents. The browser computes the hash of each inline block and compares the result against the allowlisted hashes.

host-source

A host or URL pattern specifying allowed origins. Supports wildcards for subdomains (*.example.re), specific ports (example.re:443), and path prefixes (example.re/scripts/).

scheme-source

A scheme like https: or data: allowing all resources served over the named protocol.

Example

A restrictive policy allowing resources only from the same origin blocks all inline scripts and external resource loading.

Content-Security-Policy: default-src 'self'

A policy with separate rules for scripts and images. Scripts load from the same origin only, while images also load from a dedicated image CDN.

Content-Security-Policy: default-src 'self';
  img-src 'self' images.example.re

A nonce-based policy for scripts. Each page load generates a fresh nonce, and only <script> elements carrying the matching nonce attribute execute.

Content-Security-Policy: script-src 'nonce-r4nd0m';
  style-src 'self'

A policy combining 'strict-dynamic' with a nonce. Trusted scripts are free to load additional scripts without individual host-based allowlisting.

Content-Security-Policy: script-src 'strict-dynamic'
  'nonce-r4nd0m'

A policy reporting violations to an endpoint for monitoring while enforcing the rules.

Content-Security-Policy: default-src 'self';
  report-to csp-violations

Troubleshooting

CSP violations appear in the browser console as "Refused to..." messages with the blocked resource URI and the directive responsible for the block.

  1. Inline scripts blocked after adding CSP. The browser logs Refused to execute inline script because it violates the following Content Security Policy directive: "script-src ...". The default policy blocks all inline <script> elements. Add a nonce ('nonce-abc123') to script-src and place the matching nonce attribute on each <script> tag, or add the 'unsafe-inline' keyword as a temporary measure during migration.

  2. Inline styles blocked. The console shows Refused to apply inline style when style-src does not include 'unsafe-inline' or a matching nonce/hash. Frameworks that inject styles at runtime trigger this violation. Add a nonce to style-src or use 'unsafe-inline' while transitioning to nonce-based styles.

  3. External resource blocked because the domain is missing from the directive. A Refused to load the script or Refused to connect error means the resource origin is not listed in the relevant directive. Open the browser console, identify the blocked origin from the violation message, and add the origin to the correct directive (script-src, img-src, connect-src, etc.). Check default-src as well, since missing directives fall back to the default.

  4. eval() blocked by default. Libraries relying on eval(), new Function(), or template compilers trigger Refused to evaluate a string as JavaScript. Adding 'unsafe-eval' to script-src restores the functionality but weakens the policy. Prefer refactoring code to avoid eval() where possible.

  5. Google Tag Manager or analytics scripts breaking under CSP. Tag managers inject scripts dynamically, and each injected script needs either a nonce or a host allowlist entry. Add the GTM domain (https://www.googletagmanager.com) to script-src and https://www.google-analytics.com to connect-src and img-src. For nonce-based policies, use 'strict-dynamic' so that scripts loaded by a trusted GTM script inherit trust without individual host entries.

  6. Debugging violations in the browser console. Open DevTools and check the Console tab for CSP violation messages. Each message names the blocked URI, the violated directive, and the full policy. In Chrome, the Network tab flags blocked requests with a (blocked:csp) status. Firefox provides similar detail in both the Console and Network panels.

  7. Testing a policy safely with Report-Only mode. Deploy the policy using the Content-Security-Policy-Report-Only header first. This logs violations without blocking any resources. Monitor violation reports, fix missing sources, and switch to the enforcing Content-Security-Policy header once the report stream is clean.

See also

Last updated: April 4, 2026