Your Guide to Content Security Policy

Illustration of various sources of content being vetted for security by content security policy.

What is Content Security Policy (CSP)?

A Content Security Policy (CSP) is a security feature implemented in web applications to protect against a range of attacks, particularly cross-site scripting (XSS), data injection, and clickjacking. It works by allowing web developers to specify which sources of content (e.g., scripts, styles, images) are considered safe for their website. 

Why is Content Security Policy important? 

CSPs help reduce the risk of cross-site scripting attacks, clickjacking, data injection, and packet sniffing. While it’s possible to mitigate many of these attacks in other ways, like sanitizing user input and redirecting insecure requests to the HTTPS version of the website, setting a secure CSP provides an additional layer of defense.

CSP protects against a wide variety of attacks, including some malicious browser extensions designed to inject code. The attacks a CSP can guard against are simple to execute—but they can be incredibly damaging. 

In an ideal world, malicious extensions would never make it to the marketplace. However, since dangerous extensions do exist, setting a strict Content Security Policy serves as a safeguard to prevent inline code from running.

XSS attacks affect businesses of all sizes. British Airways once fell victim to an XSS vulnerability in the Feedify JavaScript library. Attackers took advantage of that vulnerability and were able to skim credit card data for 380,000 transactions before the breach was discovered.

Content security policies can’t prevent all attacks. They’re enforced by the browser and sophisticated users can override them. However, they go a long way toward protecting the average end-user.

Common threats

Let’s consider some common threats and how they can impact your users:

Cross-site scripting (XSS)

With XSS, a common vulnerability, malicious scripts are injected into trusted websites with the intent of stealing a cookie/session token or tricking the user into taking an action. XSS attacks are easy to carry out and can be highly destructive. Because of this, malicious actors often use automated scanning tools to find vulnerable websites.

Clickjacking

Clickjacking attacks involve embedding invisible (or disguised) HTML elements into a page, tricking the user into clicking a malicious link. To give a relatively benign example, an attacker might manipulate the layout of a page to fool someone into thinking they’re “liking” a specific Facebook page when the link leads to a different one.

Data injection

Malicious actors use data injection attacks to fool systems into executing malicious code. XSS attacks are a form of data injection. HTTP header injections and SQL injections are also of concern to developers. There are many types of data injection attacks, and CSPs can only protect against some of them, so it’s essential to have other safeguards in place.

How does Content Security Policy work?

Developers can set a Content-Security-Policy header, which gets sent to the browser when a user accesses a web page. This policy tells the browser where certain content types, such as JavaScript, CSS, fonts, and embeddable objects, can be loaded from. It’s also possible to define the Content-Security-Policy in a meta tag.

The CSP can also help reduce the risk of packet sniffing attacks by dictating the protocols that can be used to transfer data. When used in conjunction with the Strict-Transport-Security response header and redirecting HTTP requests to HTTPS instead, it’s possible to block unencrypted data transfers.

The Content Security Policy contains a set of directives that serve as an allow-list for specific types of content. It’s good practice to set a strict default-src directive as a fallback, which the browser will treat as the default security policy if there isn’t a more specific applicable rule.

For example, if a web developer wants to ensure all content gets loaded from the same host, port, and protocol as the original page, they’d use the declaration of:

Copy Code
Content-Security-Policy: default-src 'self';

However, as the site grows more complex, the developer may find themselves using scripts hosted on third-party sites and decide to permit them explicitly:

Copy Code
Content-Security-Policy: default-src ‘self’; script-src ‘self’ coolscripts.example.com;

A Content Security Policy can cover images, videos, and iframes. The CSP listed above would prevent embedded YouTube videos from loading. To permit them, set the frame-src:

Copy Code
Content-Security-Policy: frame-src youtube.com www.youtube.com;

While setting default-src is considered best practice, it’s not mandatory. If there’s no default-src set, the browser will fall back to its default handling rules. These rules can vary dramatically depending on the browser, making the user experience unpredictable.

CSPs can also prevent inline scripts from running, which provides a valuable extra layer of protection against malicious content submitted by users (on websites that permit user posts or comments, for example). This is the default behavior unless you include the unsafe-inline value.

You can also configure your CSP to report violations. This data can then be fed into a SIEM tool to alert you to malicious attacks and potential errors in your CSP that may be degrading the end-user experience.

Copy Code
Reporting-Endpoints: csp-endpoint="https://example.com/report-csp-violation"

Content Security Policy best practices

A carefully defined CSP can significantly improve the security of your web application. For optimal results, keep the following best practices in mind when defining a CSP:

  • Use default-src to catch edge cases, and set this directive to be as restrictive as possible, ideally just ‘self’.
  • Avoid unsafe-inline and unsafe-eval, as they significantly reduce the effectiveness of your CSP.
  • Use restrictive settings, and only allow the hosts and protocols you actively need.
  • Avoid “*” wildcards, perhaps with the exception of permitting subdomains of domains you control.

Nonces

If you want to permit the use of inline styles or JavaScript, you can make it more secure by using a nonce. Nonces are unique strings generated each time a page is requested. They can be added to the CSP header/tag and the attributes of the relevant inline tags.

The browser will only apply the CSS or execute the JavaScript if the nonce in the CSS/javascript matches the one in the CSP.

Simply define the following in your CSP:

Copy Code
Content-Security-Policy: script-src ‘nonce-cE3Iu9HEt745’;

Then, use the nonce in your scripts:

Copy Code
<script nonce=’cE3Iu9HEt745’>
	thisWillRun();
</script>

<script>
	thisHasNoNonceSoWillNotRun();
</script>

WordPress provides the wp_create_nonce() function, which can generate a nonce each time a page loads for inclusion in the Content Security Policy header or meta tag. We offer expert guidance on ensuring that any inline scripts added to your site include the nonce correctly.

For example, we can help with custom development support and security audits to help your team implement nonces securely and in line with best practices.  We also often work directly with your development team to ensure compliance with CSP requirements and maintain strong site security.

Testing your security policy

When implementing a Content Security Policy, developers often overlook certain content types or trusted remote hosts. A policy that’s too restrictive can result in unexpected behaviors that degrade the user experience.

To reduce the risk of problems when rolling out a new CSP or changes to your existing CSP, use the report-only mode to test the policy before setting it live. This mode will trigger a report whenever the CSP gets violated, but the user will still be able to navigate and interact with the website as normal.

CSP violation reports are sent as a POST request in JSON format:

Copy Code
{
  "csp-report": {
    "blocked-uri": "http://malicious-site.example.com/keylogger.js",
    "disposition": "report",
    "document-uri": "http://example.com/login.html",
    "effective-directive": "script-src-elem",
    "original-policy": "default-src 'none'; script-src ajax.googleapis.com; report-uri /_/csp-reports",
    "referrer":"  ",
    "status-code": 200,
    "violated-directive": "script-src-elem"
  }
}

Any website that generates even a moderate amount of traffic will probably see a lot of CSP violation reports. However, most will be generated by automated scripts looking for vulnerable websites.

To help parse the reports, it’s a good idea to use a tool such as Sentry or DataDog. These cloud services can capture reports and provide a dashboard for filtering and generating visualizations. 

Once you’re satisfied that your Content Security Policy isn’t flagging any false positives, you can remove the report-only flag and set it live.

Secure your WordPress website today

The Content Security Policy header/meta tag is an important security tool. WordPress developers can benefit from having a well-defined CSP because it decreases the website’s attack surface and may help guard against vulnerabilities introduced by outdated or poorly coded plugins and themes. If you want to know more about how WordPress VIP can help you improve your WordPress Security or need assistance with defining your CSP, contact us today to book a consultation.

Get the latest content updates

Want to be notified about new content?

Leave your email address and we’ll make sure you stay updated.