What is a Content Security Policy? How to implement CSP

S
Secuirty Team

10 min read

What is a Content Security Policy? How to implement CSP

Modern websites rely heavily on JavaScript, third-party tools, and dynamic content, but every external resource added to a website can also introduce security risks. One of the most effective ways to reduce those risks is by using a Content Security Policy (CSP). 

This security mechanism helps browsers control which resources are allowed to load and execute, making it significantly harder for attackers to inject malicious scripts or exploit cross-site scripting (XSS) vulnerabilities. In this article, you will learn what a Content Security Policy is, how it works, and how to implement CSP correctly to strengthen website security without disrupting functionality.

What is a Content Security Policy?Link to heading

What is a Content Security Policy?

Content Security Policy (CSP) is a browser-level security mechanism designed to reduce the risk of common web attacks. It works by allowing a website to send a set of directives to the browser, instructing it to enforce specific restrictions on what the site's code is permitted to execute or load.

The core function of CSP is to control which resources a page can fetch, most critically, JavaScript. This makes it one of the most effective defenses against cross-site scripting (XSS), a class of attack where a malicious actor manages to inject harmful scripts into a trusted website, which then execute in a victim's browser without their knowledge.

Beyond XSS mitigation, CSP serves several additional security purposes. It can prevent clickjacking by restricting which external sites are allowed to embed your pages inside frames. It can also enforce secure connections by upgrading insecure HTTP resource requests to HTTPS automatically.

Why is CSP important in web security?Link to heading

Content Security Policy acts as an active defense layer directly within the browser, controlling what content is permitted to load and execute on a page. By enforcing strict resource source controls, CSP becomes an essential component in maintaining the integrity and security of any website.

  • Reducing XSS attacks: CSP only allows JavaScript to run from explicitly defined sources while completely blocking unsafe inline scripts and eval() calls. As a result, even if an attacker successfully injects a malicious script into the page, the browser will refuse to execute it.
  • Protecting HTTPS connections: CSP reinforces the use of HTTPS, ensuring that all data exchanged between the client and server remains encrypted. When CSP requires resources to be loaded exclusively over HTTPS, the site effectively enforces secure connections and guarantees content integrity throughout every page load.
  • Blocking untrusted content: CSP prevents a website from unintentionally loading scripts, images, iframes, and other assets from unsafe or unrecognized sources. This eliminates the risk of unintended data collection or information leakage to unwanted third parties, resulting in stronger protection against malicious code and external attacks.

>>> Why wait for an attack before improving your website security? Turn on W7SFW and stop harmful requests before they impact your WordPress site.

How CSP's security mechanism worksLink to heading

How CSP's security mechanism works

Content Security Policy is enforced by the browser based on the security policy the website delivers alongside each page response. There are two widely used deployment methods.

CSP via HTTP HeaderLink to heading

The policy is delivered to the browser through the Content-Security-Policy HTTP header, or alternatively through a meta tag in the HTML. Once the browser receives this header, it interprets it as a set of directives defining which resource sources are permitted. 

For example, if the policy declares script-src 'self' example.com, the browser will only allow JavaScript to load from the current page and from example.com, every other source is blocked.

CSP via HTML Meta TagLink to heading

CSP can also be configured directly in HTML when server-level access is unavailable. This approach suits rapid testing or applying a policy to individual pages independently. The configuration looks like this:

<meta http-equiv="Content-Security-Policy" content="default-src 'self';">

When the browser encounters this tag inside the head section, it will only permit resources to load from the current domain and automatically block all content originating from external sources.

The most important CSP directivesLink to heading

Content Security Policy is built from a collection of directives, each responsible for governing a specific category of resource on your website. The table below provides a clear reference for the most critical directives, their functions, and how to configure them.

Directive

Function

Configuration example

default-src

Sets the fallback source policy for all resource types when no specific directive is defined.

default-src 'self';

script-src

Controls which sources are permitted to load and execute JavaScript. The most critical directive for preventing XSS attacks.

script-src 'self' https://cdn.example.com;

style-src

Defines allowed sources for loading CSS stylesheets.

style-src 'self' 'unsafe-inline';

img-src

Specifies which sources are permitted to serve images on the page.

img-src 'self' data:;

font-src

Restricts font loading to trusted and explicitly approved domains.

font-src https://fonts.gstatic.com;

connect-src

Governs the origins allowed for network requests including AJAX, fetch(), WebSocket connections, and API calls.

connect-src 'self' https://api.example.com;

frame-ancestors

Determines which external sites are permitted to embed your page inside an iframe, effectively replacing X-Frame-Options.

frame-ancestors 'self';

form-action

Restricts which domains can receive data submitted through HTML forms on your page.

form-action 'self' https://secure.example.com;

media-src

Defines allowed sources for audio and video content.

media-src media1.com media2.com;

object-src

Controls sources for browser plugins and embedded content such as PDFs and Flash. Setting this to none is strongly recommended.

object-src 'none';

base-uri

Limits the values permitted in the base tag to prevent attackers from redirecting relative URLs to a malicious origin.

base-uri 'self';

How to implement a Content Security PolicyLink to heading

How to implement a Content Security Policy

Step 1: Configure the CSP Header on your serverLink to heading

The most complete way to deploy CSP is to configure the Content-Security-Policy HTTP header directly on your web server. When this header is included with every server response, the browser applies the full declared security policy and enforces strict control over which resource sources are permitted to load.

This method also provides full support for every CSP feature and is the recommended approach for systems running on Nginx, Apache, or similar platforms. Example Nginx configuration:

add_header Content-Security-Policy "<your-policy>";

Step 2: Run CSP in Report-Only mode firstLink to heading

Before enforcing CSP in production, enable the Content-Security-Policy-Report-Only header to surface all potential violations without blocking anything. In this mode, the browser does not block any resources but logs every violation to the console or sends the data to a designated endpoint via report-uri or report-to.

This allows you to identify which scripts, stylesheets, images, or API calls would be blocked under the intended policy, all without causing visual errors or degrading the user experience. Example configuration:

Content-Security-Policy-Report-Only: <your-policy>;

Step 3: Identify and allowlist all legitimate resource sourcesLink to heading

Once you have collected sufficient data from Report-Only mode, compile every valid domain your website depends on. This includes CDNs, third-party APIs, script and stylesheet origins, font providers, and communication endpoints such as WebSocket connections.

This step is critical to ensure that Content Security Policy does not incorrectly block legitimate resources when enforcement is activated. For any inline scripts that cannot be removed, migrate to nonce-based or hash-based approaches as defined in CSP Level 3, rather than permitting unsafe-inline, to maintain the highest possible security standard.

Step 4: Finalize the policy and switch to full enforcementLink to heading

Once your allowlist is complete and no significant violations remain, switch from the report-only header to the enforcing Content-Security-Policy header to activate full blocking. Under this mode, any resource originating from a source not explicitly declared in the policy will be rejected by the browser.

Ensure the policy header is sent on every server response, not just the homepage, so the browser applies it consistently across the entire site. Example enforcement configuration:

Content-Security-Policy: <your-policy>;

Step 5: Monitor and update your CSP over timeLink to heading

After deployment, regularly review reports from report-uri or report-to to catch new violations that emerge as your site evolves, whether from UI changes, new features, or newly integrated third-party services. Tools such as CSP Evaluator and browser-native security inspection panels can help you audit and refine the policy on an ongoing basis.

>>> Learn more: What Is CSRF? How to prevent Cross-Site Request Forgery

Challenges and solutions when deploying CSPLink to heading

Challenges and solutions when deploying CSP

Implementing Content Security Policy strengthens your site's security posture, but an incorrectly configured policy can break functionality or block legitimate resources. The following covers the most common deployment challenges and the practical solutions for each.

Risk of breaking page functionality: A strict CSP may block legitimate scripts or assets that were not explicitly declared, causing forms, maps, or embedded media to stop working. Running in Report-Only mode before enforcement and building the allowlist from the collected violation logs is the most reliable way to prevent this.

Handling dynamic content and inline scripts: Inline scripts and dynamically injected components, such as chat widgets, third-party counters, or interactive elements, may be blocked if CSP is not configured to account for them. Using nonces or hashes per the CSP Level 3 specification, combined with explicitly declaring permitted CDNs in the script-src directive, keeps these components functional without compromising security.

CSP does not replace secure coding practices: CSP cannot prevent XSS vulnerabilities that originate within your own codebase, particularly server-side injection flaws. Input validation, output encoding, and adherence to secure development principles remain essential and must be maintained alongside any CSP implementation.

Limited support in legacy browsers: Older browsers may not recognize or may silently ignore CSP directives, leaving the policy unenforced for a portion of your audience. The recommended approach is to identify your target browser landscape and supplement CSP with fallback mechanisms such as X-Frame-Options for platforms that lack native CSP support.

ConclusionLink to heading

A properly configured Content Security Policy is one of the most effective ways to reduce browser-based attacks and strengthen website security against modern threats such as XSS and malicious script injection. By controlling which resources are allowed to load and execute, CSP helps create a safer browsing environment without affecting the overall user experience. 

However, successful implementation requires careful testing, continuous monitoring, and a clear understanding of how your website handles scripts, external services, and dynamic content.

Related posts

Get In Touch
with our security experts.
Whether you need a custom enterprise plan or technical support, we are here to help. Expect a response within 24 hours.