Enter

Development / 13 min read

How to Implement Content Security Policy in Your WordPress Site

man using a computer with programming code projecting off the screen

Content Security Policy (CSP) is a security feature that protects your WordPress site from XSS, adware, clickjacking, spyware, and other malicious code injections by filtering the sources of your site’s resources, such as images, scripts, fonts, styles, and more.

By allowing only trusted sources to display content on your site, you ensure that you and your users are protected from bad actors who take advantage of security vulnerabilities.

Let’s explore what CSP is and how you can implement it to make your site safer.

Key Takeaways

  • Content Security Policy (CSP) is a security feature that prevents XSS and other attacks.
  • CSP is implemented through HTTP headers that filter the sources for your site’s resources (images, scripts, etc.) and only allow explicitly trusted sources to display or execute them.
  • You can implement CSP manually by editing your server configuration file or using a plugin.

What Is Content Security Policy (CSP) in WordPress?

Further down, we’ll explain how to configure CSP on your WordPress site.

Content Security Policy (CSP) is a security feature that helps prevent various types of attacks on WordPress sites, such as cross-site scripting (XSS), clickjacking, adware or spyware, and other code injection attacks. The World Wide Web Consortium (W3C) establishes the guidelines for CSP.

CSP protects your site by allowing you to control which resources are allowed to load on it. Resources your WordPress site can load may include images, styles, scripts, fonts, audio, video, and more.

In practice, CSP is an HTTP header. An HTTP header is a field in an HTTP request or response that provides additional information about it. CSP is an HTTP header that web servers send to the user’s browser to control which resources the browser can load for a given web page.

Here’s an example of what CSP may look like in your site’s .htaccess file:

<IfModule mod_headers.c>
Header set Content-Security-Policy "default-src 'self'; img-src 'self' http: https: *.amazon.com;"
</IfModule>

Further down, we’ll explain how to configure CSP on your WordPress site.

Why Is Content Security Policy Important in WordPress?

CSP is essential because controlling the resources your site is allowed to load has the following benefits:

  • Preventing XSS attacks. CSP helps prevent the execution of malicious scripts injected by attackers.
  • Specifying trusted sources. Creating a whitelist or allowlist of trusted sources reduces the risk of a bad actor injecting malicious content into your site.
  • Protecting against clickjacking. Ensures your site is not embedded into a malicious site using <iframe>, an HTML element that embeds an HTML page into another.
  • Ensuring compliance. CSP helps comply with local and international security standards and regulations.

These features protect both your site and your users from malicious code, which can be particularly important in WordPress environments, where themes and plugins are often the origin of security vulnerabilities.

Content Security Policy Directives

Content Security Policy directives are the rules that define the policies for loading content on a web page. Each directive specifies the allowed sources for a specific type of resource. Here are some of the most common CSP directives and their functions.

default-src

This directive serves as a fallback for other directives. If a specific directive is not defined, the default-src policy will apply. For example, default-src 'self'; means that, by default, content can only be loaded from the site itself.

However, if another, more specific directive establishes that a resource type (such as images) can be loaded from an external domain, then your site will load images from that external domain, while all other resources must originate from your site.

script-src

Controls the sources from which scripts can be loaded. This is particularly important for preventing cross-site scripting (XSS) attacks. For example, script-src 'self' https://trustedscripts.com; establishes that scripts will only load and execute if they originate from your site’s own domain and one specified, trusted external domain.

style-src

Controls the sources from which stylesheets can be loaded.

img-src

Controls the sources from which images can be loaded.

font-src

Controls the sources from which fonts can be loaded.

connect-src

Controls the sources from which the site can load data using mechanisms like XHR, WebSockets, and EventSource.

frame-src

Controls the sources from which frames can be loaded. This is important for preventing clickjacking attacks.

media-src

Controls the sources from which media files (like audio and video) can be loaded.

object-src

Controls the sources from which plugins (like Flash, Java, etc.) can be loaded. This is useful for mitigating risks associated with vulnerable plugins.

frame-ancestors

Specifies valid parents that may embed a page using frame, iframe, object, or embed. This is useful for preventing clickjacking. For example, frame-ancestors' none'; prevents all frames from loading on your site.

form-action

Restricts the URLs which can be used as the action of HTML form elements.

base-uri

Restricts the URLs which can be used in the <base> element.

report-uri and report-to

These directives specify where the browser should send reports about policy violations.

upgrade-insecure-requests

Instructs the browser to upgrade all HTTP requests to HTTPS.

block-all-mixed-content

Prevents loading of any assets using HTTP when the page is loaded using HTTPS.

Content Policy Keywords

Content Security Policy (CSP) keywords are values that you can use within CSP directives to specify certain behaviors or allow specific sources in a concise manner. Here are the most common CSP keywords and their functions.

self

Refers to the site’s own origin, including the same scheme (HTTP or HTTPS), host, and port. For example, Content-Security-Policy: script-src 'self'; allows scripts to be loaded only from the site’s own domain.

none

Disallows all sources for the specified directive. For example, object-src' none'; prevents any object elements from being loaded.

unsafe-inline

Allows inline resources like inline <script> elements or style attributes. This weakens your security policy and should be used with caution.

For example, script-src 'self' 'unsafe-inline'; allows both scripts from the site’s own domain and inline scripts.

unsafe-eval

Allows using eval() and similar methods for dynamically creating code. This also weakens the security policy and should be avoided, if possible, especially considering eval() is not as common in modern JavaScript. For example, script-src 'self' 'unsafe-eval'; allows scripts from the site’s own domain and the use of eval().

strict-dynamic

Allows dynamically added scripts to be executed if they are added by a trusted script (one that was allowed by the policy). This requires unsafe-inline and nonce-<base64-value> or hash-<hash-algorithm>-<base64-value>. For example, script-src 'self' 'strict-dynamic' 'nonce-<base64-value>'; allows dynamically added scripts if they are added by scripts with the specified nonce.

A nonce (“number used once”) is a pseudo-random number used once for authentication. They are common for preventing XSS attacks.

data:

Allows resources to be loaded from data: URIs. For example, img-src 'self' data:; allows images to be loaded from both the site’s own domain and data: URIs.

unsafe-hashes

Allows the use of inline event handlers and JavaScript URLs when they match a hash in the policy. Use with caution.

How to Configure the Content Security Policy in WordPress?

Now that we’ve explored Content Security Policy and the most common directives and keywords, we know the basics to configuring it on our WordPress site.

There are two main ways of configuring CSP in WordPress: manually and through a plugin.

In the following sections, we will explain both methods.

Configuring the Content Security Policy Manually

If you want to implement CSP manually, you’ll have to edit your WordPress site’s server configuration file. That is, you’ll have to edit .htaccess.

Content Security Policy follows this format:

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

Where <policy-directive> consists of <directive> <value> with no punctuation between them.

Let’s explore how to manually edit the .htaccess file.

Note: Back up your site before adding CSP directives. Poorly thought-out directives can break your site, so it’s a good idea to have a backup to roll back to. We’ll explore the precautions to take when implementing CSP further down in this post.

Additional note: Test policies on a staging or development environment before implementing them on your live site.

How Manually Edit the .htaccess File

You can use various methods to edit the .htaccess file. If you have Yoast SEO, the easiest way to edit is going to Yoast > Tools from the dashboard.

The WordPress dashboard interface. The user is accessing the "Tools" option from the "Yoast SEO" submenu

On the Tools screen, scroll down until you see the File Editor link and click on it.

The Yoast SEO interface, highlight a link to the "File Editor" feature

Now scroll down until you see a text box labeled .htaccess file. If you don’t see this section, you may need to create a blank .htaccess file and upload it to your site’s root folder before it appears in the File Editor screen.

Yoast SEO's text box for modifying the .htaccess file

Now you have to open a module with the IfModule directive, then use the Header set directive, type your CSP configuration, and close the module. The following configuration is an example:

<IfModule mod_headers.c>
Header set Content-Security-Policy default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';
</IfModule>

If you don’t have Yoast SEO, you’ll have to access your core files through an FTP client like FileZilla or a hosting control panel like cPanel. .htaccess will be in the root directory (public_html). Right-click on the file, select View/Edit, and then edit it.

Keep in mind that if you’re using a shared hosting service, you may not have access to the .htaccess file and may need to talk to your provider to figure out how to implement CSP.

Configuring the Content Security Policy With a Plugin

There are multiple plugins that help you set CSP and other HTTP headers. Some are free, and some are premium.

One of the most accessible solutions is HTTP Headers. This free plugin helps you set and maintain multiple types of HTTP headers, including CSP. Remember that, in practice, CSP is implemented through an HTTP header that restricts the sources of your site’s resources.

Let’s go through the step-by-step process of implementing CSP with a plugin.

Implementing Content Security Policy with HTTP Headers

Start by searching and installing the HTTP Headers plugin. Go to Plugins > Add New Plugin. Type “HTTP Headers” in the search box. Click Install and then Activate.

WordPress's plugin search interface, highlighting the plugin "HTTP Headers"

Once installed, go to Settings > HTTP Headers

The WordPress dashboard interface. The user is accessing the "HTTP Headers" option from the "Settings" submenu

Click on the Security icon.

Interface for the WordPress plugin "HTTP Headers", highlighting the "Security" feature

You will see various HTTP headers related to security features. All are inactive by default. Click Edit on the row corresponding to Content-Security-Policy.

A list of security-related HTTP headers in the interface for the WordPress plugin "HTTP Headers", highlighting the  "Content-Security-Policy" header

Start by clicking on the On checkbox to implement the CSP HTTP header.

The "HTTP Headers" interface, highlighting the "On" checkbox that enables the Content Security Policy header for your WordPress site

Now you can add the CSP directives your site requires to protect yourself and your users.

For example, if you want your site to only load and execute scripts originating from your own domain, you can go to the script-src section and check the 'self' option, then scroll down and click on Save Changes.

Interface of the "HTTP Headers" WordPress plugin A series of checkboxes activate keywords for the "script-src" directive

What Specifications Should Your Content Security Policy Have?

You must be very careful with your directives when using CSP on your WordPress site.

Being too restrictive can prevent some pieces of content from executing because they’re not allowed to, which may break your site’s functionality. For example, some plugins and themes may also require loading external content that too-strict policies would disallow.

Conversely, being too permissive can expose your site and users to XSS and other types of attacks.

Above all, keep in mind that every site has a different CSP configuration because every site uses different sources for its styles, images, scripts, etc. So, your CSP configuration depends on your site’s specific resources and their origins.

How to Determine Which Directives You Need for Your Content Security Policy?

Implementing CSP directives involves creating a list of all resources your site uses, along with their origins, and allowing only those resources and origins in your directives. Anything else would be blocked.

Manually going through every source for every resource on your site would take a significant amount of time and is error-prone, especially if your site pulls content from multiple external sources. It’s best to use a browser extension or a plugin. 

For this example, we’re going to show you how to use the Content Security Policy (CSP) Generator extension for Chrome (also works with Edge).

Determining CSP Directives With the CSP Generator Extension

After installing the Content Security Policy (CSP) Generator extension, go to your site and enable the extension for your domain.

Step 1: Audit Your Site

To do that, click on the CSP Generator extension button, then click on Start Building Policy.

Interface for the Chrome extension "CSP Generator"

The extension will start auditing your domain and building a temporary list CSP directives.

Interface for the Chrome extension "CSP Generator"
Step 2: Visit Multiple Pages

However, the extension can only generate directives for the content it sees. As a result, you should visit multiple pages on your site. It’s not necessary to press the Start Building Policy button again. Just browse your site.

After going through various pages, you may have more reports, and the Temporary Generated Policy may have more directives than before.

Interface for the Chrome extension "CSP Generator"

The more pages you visit, the more likely you are to encounter resources from various sources, making the automated policy more comprehensive and saving you time when modifying it during deployment.

Step 3: Check Inline Resources

Now click on Next or on 3. Inline.

Interface for the Chrome extension "CSP Generator"

This section will give you a list of inline resources that you need to move to their own files for security reasons.

Interface for the Chrome extension "CSP Generator"

CSP blocks all inline resources because it’s impossible to determine whether an inline resource is intentional, unintentional, or malicious.

For this reason, CSP blocks everything, meaning that any inline resource you’ve added to your site will be blocked unless you move them to their own JavaScript/style files and make sure you have 'self' whitelisted on your policy.

Step 4: Deploy

Click on Next or 4. Deploy. You will see a text box with a list CSP directives you can paste into your .htaccess file or replicate through the HTTP Headers plugin.

Interface for the Chrome extension "CSP Generator"

As the extension suggests, you should use “report-only” mode for a while to ensure the policy is working correctly without harming your website. After you’ve confirmed it’s not causing issues, deploy it.

To use report-only mode, all you have to do is use Content-Security-Policy-Report-Only instead of Content-Security-Policy when writing your policy on .htaccess file. Here’s an example:

<IfModule mod_headers.c>
Header set Content-Security-Policy-Report-Only default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';
</IfModule>

If you’re using the HTTP Headers plugin, go to Settings > HTTP Headers > Security and click Edit on the row corresponding to Content Security Policy.

When crafting your policy, click on the “Report-Only” (for reporting-only purposes) checkbox, then scroll down and click Save Changes.

Interface for the Chrome extension "CSP Generator"

Implement Content Security on Your WordPress Site

Content Security Policy is a guideline regulated by the World Wide Web Consortium (W3C) that prevents XSS and other security vulnerabilities. CSP allows you to control which resources are allowed to load on it, helping you filter the sources for your images, styles, scripts, and other content.

In WordPress, this is a crucial security measure because it is the world’s most popular CMS and therefore many bad actors seek to inject malicious code into WordPress sites. Additionally, themes and plugins are often the origin of security vulnerabilities, so clamping down your site’s sources of content is the best way to minimize or completely eliminate unauthorized resources.

Hopefully, this post helped you understand CSP and how to implement it on your WordPress site.

If you found this post useful, read our blog and resources for more insights and guides!