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
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.
navigate-to
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.
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') toscript-srcand place the matchingnonceattribute on each<script>tag, or add the'unsafe-inline'keyword as a temporary measure during migration.Inline styles blocked. The console shows
Refused to apply inline stylewhenstyle-srcdoes not include'unsafe-inline'or a matching nonce/hash. Frameworks that inject styles at runtime trigger this violation. Add a nonce tostyle-srcor use'unsafe-inline'while transitioning to nonce-based styles.External resource blocked because the domain is missing from the directive. A
Refused to load the scriptorRefused to connecterror 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.). Checkdefault-srcas well, since missing directives fall back to the default.eval()blocked by default. Libraries relying oneval(),new Function(), or template compilers triggerRefused to evaluate a string as JavaScript. Adding'unsafe-eval'toscript-srcrestores the functionality but weakens the policy. Prefer refactoring code to avoideval()where possible.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) toscript-srcandhttps://www.google-analytics.comtoconnect-srcandimg-src. For nonce-based policies, use'strict-dynamic'so that scripts loaded by a trusted GTM script inherit trust without individual host entries.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.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-Policyheader once the report stream is clean.
See also
- Content Security Policy Level 3 (W3C)
- Content-Security-Policy-Report-Only
- Reporting-Endpoints
- HTTP headers