Content Security Policy (CSP)

Last updated:

Content Security Policy (CSP) is a layer of security created by the owners of a web application. 

An effective (strict) CSP restricts which resources are allowed to a small set of domains. This has the potential to impact Pendo by preventing Pendo from loading or operating correctly. For example, the agent might not be called or guides might not load. For this reason, you might need to make an adjustment to your CSP to allow Pendo full functionality. 

This article outlines the minimum required directives in your CSP to allow Pendo to have full functionality. If you're using Feedback, see Feedback's Content Security Policy.

CSP overview

CSP is a method of specifying domains from which specific types of content in your web application can be loaded. A CSP can specify sources that are allowed for specific types of content, such as JavaScript, CSS, and images.

CSP is often used to prevent Cross Site Scripting (XSS) and data injection attacks, especially if you manage sensitive data. You might also use CSP if you want to:

  • Ensure that page resources, such as images and frames, are only loaded from trusted sources.
  • Prevent your application from being framed by untrusted domains.
  • Transparently upgrade all resource requests to HTTPS.

You enable CSP by setting the Content-Security-Policy HTTP response header or as a meta tag on the main document. For example, an application can define a policy by setting the following header:

Content-Security-Policy: default-src https:; script-src 'nonce-{random}'; object-src 'none'

Real policies are typically more complicated. The above example policy requires all resources to load over HTTPS, allows only script elements with the correct nonce attribute, and prevents plugins from loading.

Errors caused by CSP

If you notice any of the following issues after installing Pendo, you might need to check your CSP. 

  • No analytics or guide events appearing for your application.
  • Guides not loading at all in your application.
  • Visual Design Studio not launching.
  • No replays appearing for your application.
  • Error messages in your console that look like the following:

Screenshot 2023-11-17 at 11.26.37 AM.png

Find your current CSP

To find your current CSP:

  1. Open the Network tab in your browser console.
  2. Open the request of the main page.
  3. Find the CSP listed under Content-Security-Policy in the Headers tab.

    CSP.png
  4. If there’s no CSP response header, inspect the HTML of the page and look for a Content-Security-Policy <meta> tag in the <head> of the document.

    CSP.png

Standard required directives

Required directives are different depending on your agent delivery settings. To know which directives are required for Pendo to work fully in your application, you must first take note of your guide delivery settings. To find these:

  1. Navigate to Settings > Subscription Settings.
  2. Open the Applications tab.
  3. Find and open the relevant app from your Applications list.
  4. Open the Agent Settings tab.
  5. Select Manage Production Settings.
  6. Note which option is selected: Standards, XHR, or JSONP.

The following directive changes are required for Pendo to have full functionality with a strict CSP. These are organized by the following content types:

  • JavaScript (directive: script-src)
  • CSS (directive: style-src)
  • Images (directive: img-src)
  • Data (directive: connect-src)
  • Frames (directives: frame-src and frame-ancestors)
  • Workers (directive: worker-src)

Replace SUB_ID with your Subscription ID. Your Subscription ID is displayed in the page URL when you're logged into Pendo. It uses the following formathttps://app.pendo.io/s/[SUB_ID]/. The subscription ID immediately follows /s/. Don't accidentally grab the unique ID for a guide or report that populates at the end of the URL path when navigating Pendo.

You may include https:// before any hostnames if desired.

JavaScript directive changes

Directive: script-src

The following sources (hosts) allow Pendo scripts to be downloaded and run.

Source Description
cdn.pendo.io

Location of the Pendo agent, referenced in your install script ("snippet"). This is where the Pendo agent is downloaded from by default. Needed to download Pendo.

pendo-io-static.storage.googleapis.com

Location of the Pendo agent downloaded for staging domains. Needed to download the agent on staging domains as well as the agent debugger.

pendo-static-{{ SUB_ID }}.storage.googleapis.com

Location of all guide content. Needed to download guide code blocks.

data.pendo.io

Used to download the list of guides that a visitor is eligible for. This is only needed for JSONP delivery methods.

app.pendo.io

Only required to use the the Visual Design studio.

'unsafe-inline'

Only required if using custom code blocks or classic guides in the Visual Design Studio.

'unsafe-eval'

Only required if using custom code blocks or classic guides while in the Visual Design Studio.

CSS directive changes

Directive: style-src

The following sources (hosts) allow Pendo styles to be used on your site.

Source Description
pendo-io-static.storage.googleapis.com

Default Guide CSS is loaded from this URL. Only needed if classic guides are enabled to download default guide CSS.

pendo-static-{{ SUB_ID }}.storage.googleapis.com

Guide styles and Global CSS. Needed to download global guide CSS and stylesheets for custom code blocks.

'unsafe-inline'

Used to support guide pseudo styles (hover, carets in the Resource Center, number scale) and styles when the Visual Design Studio is launched.

app.pendo.io

Only required to use the Visual Design Studio.

Images directive changes

Directive: img-src

The following sources allow images hosted by Pendo to be displayed on your site.

Source Description
cdn.pendo.io

Only needed for badges in classic guides.

data.pendo.io

Events are sent using the image src to this url. Needed to send events to Pendo.

pendo-static-{{ SUB_ID }}.storage.googleapis.com

Guide images are downloaded from this url. Needed to download any uploaded guide images.

app.pendo.io

Only required to use the designer.

data:

Default badge images. If using custom images for badges, then this isn't needed.

Data directive changes

Directive: connect-src

The following sources allow scripts on your pages to communicate with Pendo.

Source Description
data.pendo.io Required for event communication and Session Replay.
pendo-static-{{ SUB_ID }}.storage.googleapis.com

Load the guide structure files here. Needed to load guide content.

app.pendo.io

Only required to use the Visual Design Studio.

Frame directive changes

Directive: frame-src

The following source allows Pendo to load the Visual Design Studio within a <frame> over your site.

Source Description
app.pendo.io

The Visual Design Studio is loaded from this URL. Only required to design guides with the Visual Design Studio.

Directive: frame-ancestors

The following source allows Pendo to load your site pages within a <frame>, which is only needed if you're using the Classic Designer.

Source Description
app.pendo.io

The Pendo host from where the Classic Designer loads your application. Only required to design guides with the Classic Designer.

Workers directive changes

Directive: worker-src

The following source allows the Pendo agent to start a worker thread to minimize performance impact on your application.

Source Description
blob:

The Pendo agent starts a web worker to compress and send session-capturing data for Session Replay. Offloading work to a worker allows for improved performance of session capturing.

Location-based changes

This section lists location-based changes to the source for EU, US1, and Japan customers.

EU

Original
EU
app.pendo.io app.eu.pendo.io
data.pendo.io

data.eu.pendo.io

cdn.pendo.io

cdn.eu.pendo.io

pendo-io-static.storage.googleapis.com

pendo-eu-static.storage.googleapis.com

pendo-static-{{ SUB_ID }}.storage.googleapis.com

pendo-eu-static-{{ SUB_ID }}.storage.googleapis.com

US1

Original
US1
app.pendo.io us1.app.pendo.io
data.pendo.io

us1.data.pendo.io

cdn.pendo.io

us1.cdn.pendo.io

pendo-io-static.storage.googleapis.com

pendo-us1-static.storage.googleapis.com

pendo-static-{{ SUB_ID }}.storage.googleapis.com

pendo-us1-static-{{SUB_ID}}.storage.googleapis.com

Japan

Original
Japan
app.pendo.io app.jpn.pendo.io
data.pendo.io

data.jpn.pendo.io

cdn.pendo.io

cdn.jpn.pendo.io

pendo-io-static.storage.googleapis.com

pendo-jp-prod-static.storage.googleapis.com

pendo-static-{{ SUB_ID }}.storage.googleapis.com

pendo-jp-prod-static-{{SUB_ID}}.storage.googleapis.com

Required directives for custom CNAME

If you're using CSP with CNAME, add the sources below to the existing Pendo standard required directives while setting up CNAME with Pendo's Support team. After CNAME configuration is complete, directives can be trimmed down.

JavaScript directive changes

Directive: script-src

The following sources (hosts) allow Pendo scripts to be downloaded and run.

Source Description
content.pendo.example.com

Location of the Pendo agent and guide content.

data.pendo.example.com

Used to download the list of available guides for the JSONP guide-delivery method.

app.pendo.io

Only required to use the the Visual Design studio.

'unsafe-inline'

Only required if using custom code blocks or classic guides in the Visual Design Studio.

'unsafe-eval'

Only required if using custom code blocks or classic guides while in the Visual Design Studio.

CSS directive changes

Directive: style-src

The following sources (hosts) allow Pendo styles to be used on your site.

Source Description
content.pendo.example.com

Guide styles, global CSS, and default CSS are loaded from this domain.

'unsafe-inline'

Used to support guide pseudo styles (hover, carets in the Resource Center, number scale) and styles when the Visual Design Studio is launched.

app.pendo.io

Only required to use the Visual Design Studio.

Images directive changes

Directive: img-src

The following sources allow images hosted by Pendo to be displayed on your site.

Source Description
content.pendo.example.com

Guide images are downloaded from this URL.

data.pendo.example.com

Events are sent using the image src to this url. Needed to send events to Pendo.

app.pendo.io

Only required to use the designer.

data:

Default badge images. If using custom images for badges, then this isn't needed.

Data directive changes

Directive: connect-src

The following sources allow scripts on your pages to communicate with Pendo.

Source Description
data.pendo.example.com Required for event communication and Session Replay.
content.pendo.example.com

Load the guide structure files here. Needed to load guide content.

app.pendo.io

Only required to use the Visual Design Studio.

Frame directive changes

Directive: frame-src

The following source allows Pendo to load the Visual Design Studio within a <frame> over your site.

Source Description
app.pendo.io

The Visual Design Studio is loaded from this URL. Only required to design guides with the Visual Design Studio.

Directive: frame-ancestors

The following source allows Pendo to load your site pages within a <frame>, which is only needed if you're using the Classic Designer.

Source Description
app.pendo.io

The Pendo host from where the Classic Designer loads your application. Only required to design guides with the Classic Designer.

Workers directive changes

Directive: worker-src

The following source allows the Pendo agent to start a worker thread to minimize performance impact on your application.

Source Description
blob:

The Pendo agent starts a web worker to compress and send session-capturing data for Session Replay. Offloading work to a worker allows for improved performance of session capturing.

Compatible guide content

While Pendo is compatible with strict CSP directives, it is the user’s responsibility to ensure the guide content is compatible with your CSP restrictions.

If unsafe-inline is not present within the style-src and script-src directives, inline CSS and JavaScript within the HTML tab of the guide will not function correctly. To prevent an unexpected guide experience, all inline styles and scripts should be moved to the CSS and JS tabs of the guide code block or template.

With properly set minimal CSP directives (no inline directives), you should be able to fully use the Pendo Designer to show and tag your features. The X-Frame-Options plugin should enable you to use the Designer in guide editing mode with strict CSP. It is important to test guide content outside of the designer and with the X-Frame-Options plugin turned off.

Example of strict CSP compatible content

The basic concept is to remove all "unsafe-inline" styling and JavaScript.

For example, all of the inline styling and JavaScript within this HTML button:

<button class="_pendo-guide-next_" style="color:blue;" onclick="pendo.onGuideAdvanced()">Next</button>
would be distributed across the HTML, CSS, and JS tabs of the guide. The below example illustrates how to break down elements in guide content. You or your team’s developers may have a different or even better approach:

HTML

<button class="_pendo-guide-next_ blue-button">Next</button>

CSS

.bluebutton { color: blue; }

JavaScript

(function wireGuideAdvanceButton (step) { step && step.attachEvent(step.guideElement[0], 'click', function (e) { var advanceButton = pendo.dom(e.target || e.srcElement).closest('._pendo-guide-next_'); if (advanceButton.length) { pendo.onGuideAdvanced(); } }); })(step,guide);

Trusted types

Trusted types are an experimental technology currently only supported by Chromium-based browsers. If your application requires the extra XSS protection provided by trusted types, add the following directive to your CSP header: trusted-types pendo;. Trusted types support requires agent version 2.184.0 or higher.

X-Frames-Options header

We strongly recommend using the frame-ancestors directive from the official Content Security Policy (CSP) Level 2 specification instead of using the unofficial X-FRAME-OPTIONS header.

If switching to CSP is not an option, you can still use the Pendo in-app designer one of two ways:

  • Browser plugin. These are created by third parties, which means that Pendo doesn't own or maintain either of the extensions.
  • Updating the ALLOW-FROM value. We tested this on Firefox 43. This isn't an official standard and there are various implementations that might not support this value. You must specify the app.pendo.io URI. You can only include one URI per ALLOW-FROM, separated by a semi-colon. X-Frame-Options: ALLOW-FROM https://app.pendo.io

Additional Resources

 
Was this article helpful?
7 out of 12 found this helpful