Table of Contents
Content Security Policy (CSP)
Content Security Policy (CSP) is a security standard implemented through HTTP headers or meta tags that helps prevent cross-site scripting (XSS) attacks, clickjacking, code injection, and other web vulnerabilities by controlling which resources a browser is allowed to load and execute on a web page.
If you’ve ever seen a browser console error saying “Refused to load the script because it violates the following Content Security Policy directive,” you’ve encountered CSP doing its job.
This guide explains what CSP is, why it matters, how to implement it, common directives, and how CSP fits into modern web security practices.
What Is Content Security Policy?
Content Security Policy is a browser security mechanism that lets website owners define a whitelist of trusted sources for various types of content. When a browser loads a page with a CSP header, it enforces those rules by blocking any resources that don’t match the policy.
How CSP works in practice:
A website sends a CSP header with the HTTP response. The header contains directives that specify which sources are allowed for different resource types. The browser reads this header and enforces the policy for that page.
Example CSP header:
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; img-src *
This policy means:
default-src 'self': By default, only load resources from the same origin (the website’s own domain)script-src 'self' https://cdn.example.com: JavaScript can only load from the same origin or from cdn.example.comimg-src *: Images can load from anywhere
If a script tries to load from https://malicious-site.com, the browser blocks it because that domain isn’t in the script-src whitelist.
Why Content Security Policy Matters
Modern websites pull resources from dozens of sources: JavaScript libraries from CDNs, analytics scripts from Google or Plausible, payment processing from Stripe, advertising networks, social media widgets, and more. Each of these represents a potential attack vector.
The attack scenario CSP prevents:
An attacker compromises a third-party script your site loads. They inject malicious JavaScript that steals user credentials, injects phishing forms, or redirects users to malware sites. Without CSP, your users are vulnerable even though your own server was never compromised.
With CSP properly configured:
Even if the attacker compromises a third-party service, they can’t inject new scripts from unauthorized domains. The browser blocks the attack before it executes. CSP acts as a last line of defense when other security measures fail.
Additional attack types CSP mitigates:
- Clickjacking: Attackers embed your site in an invisible iframe and trick users into clicking buttons they can’t see. CSP’s
frame-ancestorsdirective prevents unauthorized sites from framing your content. - Data exfiltration: Malicious scripts might try to send user data to external servers. CSP’s
connect-srcdirective limits which endpoints scripts can communicate with. - Inline script injection: Many XSS attacks inject
<script>tags directly into page content. CSP can block all inline scripts by requiring scripts to come from external files in whitelisted locations.
Common CSP Directives
CSP provides granular control through specific directives for different resource types.
default-srcsets the fallback policy for any resource type not explicitly defined. It’s the baseline for your security policy.script-srccontrols where JavaScript can load from. This is one of the most important directives because malicious scripts are the primary attack vector for most web exploits.style-srccontrols stylesheets. Less critical than scripts but still important to prevent CSS injection attacks.img-srccontrols image sources. Often set permissively (img-src *) because images pose less security risk than executable code.connect-srccontrols which servers scripts can connect to via XMLHttpRequest, fetch, WebSocket, and EventSource. Critical for preventing data exfiltration.font-srccontrols font sources. Fonts can contain embedded scripts in some formats, so restricting their sources prevents certain attack vectors.frame-ancestorscontrols which sites can embed your page in frames or iframes. This prevents clickjacking and unauthorized embedding.form-actionrestricts where forms can submit data. Prevents attackers from modifying form actions to send user input to malicious servers.upgrade-insecure-requestsautomatically upgrades HTTP requests to HTTPS. Useful for migrating sites from HTTP to HTTPS without breaking functionality.
Implementing Content Security Policy
CSP can be implemented through HTTP headers (recommended) or HTML meta tags (less flexible but easier for static sites).
HTTP Header Implementation
Set the header on your web server. The exact method depends on your server software.
Apache (.htaccess or config):
Header set Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com"
Nginx (config):
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com";
Node.js/Express:
app.use((req, res, next) => {
res.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'self' https://cdn.example.com");
next();
});
Meta Tag Implementation
For static sites without server configuration access, use a meta tag in the HTML head:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://cdn.example.com">
Limitations of meta tag CSP: The frame-ancestors, sandbox, and report-uri directives don’t work in meta tags. HTTP headers provide full CSP functionality.
CSP Reporting and Testing
CSP includes a reporting mechanism that sends violation reports to a specified endpoint without blocking the violating resources. This lets you test policies before enforcing them.
Content-Security-Policy-Report-Only header:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-violation-report
This header reports violations but doesn’t block them. Your server endpoint receives JSON reports of what would have been blocked, letting you refine the policy before enforcement.
Example violation report:
{
"document-uri": "https://example.com/page",
"violated-directive": "script-src 'self'",
"blocked-uri": "https://malicious-site.com/script.js",
"source-file": "https://example.com/page",
"line-number": 42
}
Testing workflow:
- Implement CSP in report-only mode
- Monitor violation reports for several days
- Identify legitimate resources that need to be whitelisted
- Update the policy to include necessary sources
- Switch from report-only to enforcing mode
Common CSP Challenges and Solutions
Inline scripts and styles: Many sites use inline JavaScript and CSS. CSP blocks these by default for security reasons. Solutions include moving scripts to external files, using nonces, or using hashes.
Nonces (recommended): Generate a random token for each page load and include it in the CSP header and in the script tag:
Content-Security-Policy: script-src 'nonce-rAnd0mT0k3n'
<script nonce="rAnd0mT0k3n">
// This script is allowed
</script>
Hashes: Calculate the SHA256 hash of the inline script and whitelist it:
Content-Security-Policy: script-src 'sha256-xyz123...'
Third-party services: Many third-party services (analytics, ads, social widgets) load additional scripts dynamically. You need to whitelist not just the initial script source but also any domains those scripts load from. This often requires reading documentation or trial and error with report-only mode.
eval() and dynamic code: CSP blocks eval(), new Function(), and other forms of dynamic code execution by default. Some frameworks rely on these. Solutions include refactoring code to avoid dynamic execution or using 'unsafe-eval' (which weakens security).
CSP and Modern Web Development
Modern JavaScript frameworks and build tools have varying levels of CSP compatibility.
- React, Vue, Angular: These frameworks work well with CSP when built for production. They don’t use
eval()in production builds. However, development servers often useeval()for hot reloading, so you may need different CSP policies for development and production. - Webpack, Vite, Parcel: Modern bundlers support CSP-compatible builds. Configure your build tool to generate nonce or hash values for inline scripts.
- CDNs and static assets: Content served from CDNs needs to be whitelisted. This is straightforward but requires keeping the CSP updated when you change CDN providers.
CSP and Antidetect Browsers
When using antidetect browsers like Multilogin for multi-account management, CSP policies on websites you access don’t interfere with browser functionality. CSP controls what resources the website can load, not how your browser is configured or what fingerprint it presents.
If you’re developing web applications that users will access through various browsers (including antidetect browsers), implementing CSP is a best practice that protects both you and your users from injection attacks regardless of their browser choice.
Summary: CSP Best Practices
- Start with report-only mode to identify legitimate resources before enforcing
- Use specific directives rather than overly permissive policies
- Avoid
'unsafe-inline'and'unsafe-eval'whenever possible; use nonces or hashes instead - Whitelist only necessary domains for each resource type
- Test thoroughly across different browsers and user flows
- Monitor violation reports to catch new issues after deployment
- Update policies as your site evolves and adds new third-party services
Content Security Policy is one of the most effective web security mechanisms available. While implementation requires initial setup and testing, the protection against XSS, injection attacks, and clickjacking makes CSP essential for any site handling sensitive user data or operating in security-conscious environments.
Related Topics
HTML5 Storage
HTML5 Storage is a set of web technologies designed to provide a way to store data locally within the user’s browser. Read more here.
Page Visibility API
The Page Visibility API is a browser feature that allows developers to detect and respond to changes in the visibility state of a web page. Read more here.
Behavior-Based Fingerprint
Script injection is when attackers insert malicious code into an otherwise benign or trusted website or application. Read more here.
Black Hat SEO
Black hat SEO uses manipulative tactics that violate search guidelines. Learn common techniques like keyword stuffing, cloaking, link schemes, and the risks.