Software

Hop CSP Header

Current Version: 1.1.0
  • EE6
  • EE7
  • Overview

    Can’t wait to get started? Here’s the quick overview.

    When you first install Hop CSP Header, it is set to operate in Report-Only mode. As your visitors browse the site, HOP CSP Header logs all potential violations.

    Let it run a while in this mode and Hop CSP Header will collect violation reports without blocking any content from your site. We recommend you run Hop CSP Header in Report-Only Mode for a week on high-traffic websites, or that you install it and then run a site crawler.

    This is also the time for you to modify your templates to properly include a nonce.

    At the end of the Report-Only phase, review the violation record and finalize your CSP header options.

    Then switch on Enforce Mode to begin actively blocking violations and improving security.

    You can review, adjust, and selectively enable or disable rules at any time through the control panel.

  • What is a CSP?

    A site’s Content Security Policy is a security mechanism that works to eliminate cross-site scripting attacks by specifying a number of rules about XSS behaviors.

    It requires your server to pass a header to the user’s browser. That header, the CSP header, specifies what resources (scripts, styles, images, etc.) that browser is permitted to load from other servers, and it specifies specifically which domains are allowed (values) for what types of resources (directives).

    Your CSP Policy is made of rules. Rules are grouped by directives. Directives describe all the different types of content and behaviors a site might want to allow, such as img-src, frame-src, form-action, etc. You may be surprised how many rules are necessary to describe the content-interacting behaviors of visitors to your site.

    A good CSP header policy should also contain a nonce, which is a specific token that is used to validate code that calls to other resources, inline or on other servers.

    And finally, a CSP header can also specify if and how the browser should report requests that are not allowed by the current rules.

    Read more about Content Security Policy on Wikipedia and on MDN Docs.

  • Step 1: Install the Add-on

    1. Unzip the folder to a temporary location on your local hard drive.
    2. FTP the files from their local folders to the same locations in your EE install’s /system/user/addons/ folder on the server.
    3. Navigate to Add-ons in your EE control panel and install the add-on. That’s it!

  • Step 2: Collect Violations

    After installing Hop CSP Header, a default CSP header will be attached to your site. Here’s a very simple (and incomplete) example of one.

    Content-Security-Policy: Content-Security-Policy-Report-Only: connect-src 'self' https://analytics.google.com report-uri https://example.com/?ACT=172

    This initial CSP header will not tell the browser to block anything yet. It tells each browser to behave as before, and report violations of CSP policy rules back to the EE server. If a report is made and tracking is turned on (see below), Hop CSP Header logs and caches these reports for later review.

    Note: If you use Speedy Static Page Caching, you must manually copy the generated CSP header value into your .htaccess file, because static pages are not directly served by EE, and so will not get the CSP header.

    Note: Strict mode will not work for cached pages, because Strict mode requires a dynamic nonce values, and a nonce value cannot be updated on each request for a static page.

  • Step 3: Review List of Policies

    By default, tracking is turned on and all newly discovered violations of your CSP are automatically saved in to the list of policy rules in an inactive state.

    Look them over, and review and fine-tune the logged violations.

    Select the checkbox for those items you want to allow. Then click Save to apply them all and include them in the active CSP header.

    A preview of the header is shown further down the page.

  • Step 4: Adjust Settings

    While the defaults are meant for a safe initial install, a proper installation of Hop CSP Header will likely require changes to your site’s templates and add-ons, as well as regular monitoring to ensure that no site visitor is getting a degraded experience because of the additional security.

    Adjust the following settings to get full benefits out of Hop CSP Header.

    Note: When you are tracking violations, requests that match an active policy rule will not be reported. So if your policy rules are perfect, you’ll get no violations needing reporting, and no return traffic. However, if an XSS attack or new element is added to your site, you may suddenly get a LOT of reports, potentially on every page load – which is why leaving tracking on permanently is not recommended.

    Note: Use your browser’s DevTools → Network tab → search for requests to ?ACT=[generated-ACT-ID] to spot and study new reports.

    Note: Review and adjust your CSP periodically as your site evolves.

    Here are the settings you can adjust.

  • Enforce Policies

    When enabled, EE will add a CSP header to every page served. That header will enforce all active (checked) rules.

    Off (default): Violations will not be blocked.

    On: CSP is fully enforced. Violations are blocked.

  • Track Violations

    When enabled, browsers will report potential CSP violations back to the site. New unique violations will be logged in the Content Security Policy rules.

    Off: Violations will not be logged.

    On (default): Active CSP rules will be compiled into a Content-Security-Policy-Report-Only header. New violations will be logged.

    For efficiency and especially on high-traffic sites, you should leave this disabled once you have generated your rule set and unless you are actively monitoring this add-on. Violations can generate a lot of database inserts and processing.

  • CSP Header

    Technically not a setting. The rules above will be automatically consolidated and merged, then shown here as the header that will be sent by EE for each page served.

    Yes, it is a hard-to-read jumble, but it’s easy to copy and paste this into an .htaccess file.

    Note: In .htaccess, you can probably put quotes around the whole value and then add line breaks if you escape them with a backslash, like this:

    Header always set Content-Security-Policy " \ default-src 'self'; \ script-src 'self' \ https://consent.cookiebot.com/"

    NOTE: If you are having problems with your .htaccess file, get in touch. While .htaccess fixes are beyond the scope of this add-on’s direct support, we’d love the chance to assist you with your unique situation.

  • Add Nonce for Scripts

    If this is enabled:

    If you have any active rules with any of the following script directives, Hop CSP Header will automatically include the dynamic or static nonce value in them:

    script-src script-src-elem (if specified in other rules)

    NOTE: If you do not want to use a nonce for scripts, make a rule for script-src with value ‘unsafe-inline’. If you specify ‘unsafe-inline’, the browser will ignore all nonce or hash values for that directive. ‘unsafe-inline’ takes precedence and allows inline <script> elements to be parsed regardless of whether they have a valid nonce. HOWEVER, since the main point of a CSP header is to ensure your code is safe and not to allow any random code to run, it’s probably best not to use ‘unsafe-inline’.

  • Add Nonce for Styles

    If this is enabled:

    If you have any active rules with any of the following style directives, Hop CSP Header will automatically include the dynamic or static nonce value in them:

    style-src style-src-elem (if specified in other rules) style-src-attr (if specified in other rules)

    NOTE: If you do not want to use a nonce for styles, make a rule for style-src with value ‘unsafe-inline’. If you specify ‘unsafe-inline’, the browser will ignore all nonce or hash values for that directive. ‘unsafe-inline’ takes precedence and allows inline <style> elements to be parsed regardless of whether they have a valid nonce. HOWEVER, since the main point of a CSP header is to ensure your code is safe and not to allow any random code to run, it’s probably best not to use ‘unsafe-inline’.

  • Nonce (static)

    A nonce (“number used once”) is a unique, random token that appears in the header and should match the nonces used in your page’s HTML. This nonce matching ensures that only trusted inline scripts and styles are executed.

    By default, EE uses this static value. However, the nonce value is generated dynamically when Dynamic Nonce Mode is enabled.

    To allow inline code to run with a nonce, add the nonce (whether static or dynamic) to your code like so:

    <style nonce="{hop_csp_header_nonce}"> p {color: red} </style> or <script nonce="{hop_csp_header_nonce}"> console.log('Nonce worked'); </script>

    You can also hard-code the nonce value displayed here into your templates – but why would you do that?

  • Dynamic Nonce Mode

    Recommended for tightest security.

    When enables, a new, random nonce is generated on every page load (somewhat like a CSRF token). Inline <script> and <style> tags must match this nonce.

    When Dynamic Nonce Mode is disabled, a static nonce is used across all requests.

    Inline <script> and <style> tags must use a nonce attribute. and dynamic {hop_csp_header_nonce} value, like so <script nonce="{hop_csp_header_nonce}"></script>

    If your site uses static page caching, or your template is cached, you must disable Strict Mode and use a static nonce.

    Note: EE’s CSRF token doesn’t get cached because of some code in EE Core. The CSP nonce is not as lucky, and therefore needs less caching to work dynamically.

  • Other Advice about Content Security Policy

    Here are some tips to help you with CSP rules, which can be quite complex:

    1. You can sort by notes, directive, and value.
    2. If you see violations related to inline, identify the corresponding <script> or <style> tags and add nonce="{hop_csp_header_nonce}" to them.
      If that’s not possible, consider using ‘unsafe-inline’ — but only as a last resort.
      Once you’ve added the nonce code, go back and remove the rows containing the inline value. Then try loading the same page again to verify the fix.
    3. Maintaining a strong CSP for inline styles is challenging, especially when using third-party services that inject their own styles.
      That said, violations of inline styles are typically less severe than those involving scripts.
    4. If you do not specify style-src-elem or style-src-attr, the style-src directive will apply to both. However, if either style-src-elem or style-src-attr is defined, style-src will no longer serve as a fallback. In that situation, you should manually define all shared sources using both those directives.
    5. The same applies to script-src and script-src-elem. If script-src-elem is defined at all, script-src does not also get definied by default. Any sources that should apply to both must be explicitly added to each.
    6. In some cases, violations may get logged multiple times with identical details. While the generator will de-duplicate the final policy, it’s a good idea to manually remove duplicates to keep your rule list clean and easy to manage.

    NOTE: Whatever questions you have about Hop CSP Header or CSP headers in general, please get in touch so we can assist you.

  • Add-on Developers

    If you are an add-on developer, be mindful of any script or style tags you insert directly into templates.

    If you can’t use EE’s JS and CSS generating functions, then use ee('hop_csp_header:Service')->getNonce() to retrieve the current nonce value and apply it consistently across your templates and scripts.

    You can scan your ExpressionEngine codebase for raw <script> tags that may need to be updated manually. Common locations include:

    ee/ExpressionEngine/Library/Captcha.php ee/ExpressionEngine/Legacy/Typography.php

    Note: It is also possible to validate XSS resources using a hash i.e. a checksum on the external file. This approach may work well for your add-on, however, it is outside the scope of Hop CSP Header.

Have a Project for Us?

Request a Proposal