Skip to main content
Version: 9.4

Content Security Policy (CSP) for Qrvey Integrations

The Content Security Policy (CSP) is a browser security mechanism that protects applications from attacks such as Cross-Site Scripting (XSS) and data injection.

If your application does not enforce a CSP, no configuration is required. However, if your organization enforces a strict CSP, you must explicitly allow Qrvey resources so that embedded widgets and content can load correctly.

Base CSP Example

You can use the following base policy configuration as a starting point:

default-src 'self';
img-src 'self' data: blob: https://QRVEYINSTANCE.qrveyapp.com;
script-src 'self' 'nonce-NONCE_VALUE' https://QRVEYINSTANCE.qrveyapp.com;
worker-src 'self' blob:;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://QRVEYINSTANCE.qrveyapp.com;
font-src 'self' https://fonts.gstatic.com https://QRVEYINSTANCE.qrveyapp.com;
connect-src 'self' https://QRVEYINSTANCE.qrveyapp.com wss://QRVEYINSTANCE.qrveyapp.com https://maps.geo.us-east-1.amazonaws.com https://tiles.openfreemap.org;
media-src 'self' data: blob:;
frame-src 'self' blob:;
object-src 'none';
base-uri 'self';

Replace QRVEYINSTANCE

  • Replace all occurrences of QRVEYINSTANCE.qrveyapp.com with the actual domain where your Qrvey platform is hosted. This can be:

    • The Qrvey-managed instance domain assigned to your organization.

      OR

    • A custom domain configured for your deployment (for example, analytics.customerdomain.com).

    Important: The QRVEYINSTANCE value must match the domain where Qrvey is installed and from which your widgets are being loaded.

  • Replace NONCE_VALUE with the nonce your server generates for each page request. Do not use a fixed value.

  • Replace us-east-1 in maps.geo.us-east-1.amazonaws.com with the AWS region where your Qrvey instance is hosted.

Add a Nonce to Your Script

Qrvey widgets authorize their own scripts using CSP nonces, which allows you to maintain a strict script-src policy.

  1. Generate a random nonce for each page request. The following example shows server-side nonce generation:

    crypto.randomBytes(16).toString('base64')
  2. Add the nonce to the script-src:

    script-src 'self' 'nonce-NONCE_VALUE' https://QRVEYINSTANCE.qrveyapp.com;
  3. Add the value to a meta tag at the top of your <head> element, before any Qrvey widget script. The content meta tag and the header value must be identical:

    <meta name="csp-nonce" content="NONCE_VALUE" />

Qrvey automatically reads and applies the nonce from the meta tag.

Additional Instructions

  • Use a cryptographically secure random generator with at least 16 bytes of entropy. Do not use Math.random(), a timestamp, or a per-session value.
  • If your application currently includes 'unsafe-inline' in script-src, remove it. Browsers ignore 'unsafe-inline' in any directive that contains a nonce, so leaving it in place has no effect.
  • If your HTML is served from a CDN or static host with no per-request processing, generate the nonce and set the header in an edge function (for example, a CloudFront Function or a Cloudflare Worker) rather than at build time.
  • To prevent serving a nonce from cache, send Cache-Control: no-store when serving the HTML document that loads the widget.

Directive Details

DirectiveDescription
default-src 'self'Sets the default content source to your own domain.
img-src 'self' data: blob: https://QRVEYINSTANCE.qrveyapp.comAllows images from your domain, your Qrvey instance, inline image data, and blob URLs. Sufficient for dashboards embedded in Interact mode.
script-src 'self' 'nonce-NONCE_VALUE' https://QRVEYINSTANCE.qrveyapp.comPermits scripts from your domain and your Qrvey instance. Required for widget initialization and execution. The nonce is supplied by your server. Qrvey applies it automatically.
worker-src 'self' blob:Allows web workers, required for background operations.
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://QRVEYINSTANCE.qrveyapp.comEnables inline styles and stylesheets from Qrvey and Google Fonts. 'unsafe-inline' is required for widget functionality and cannot be removed.
font-src 'self' https://fonts.gstatic.com https://QRVEYINSTANCE.qrveyapp.comAllows font loading from Qrvey and Google Fonts.
connect-src 'self' https://QRVEYINSTANCE.qrveyapp.com wss://QRVEYINSTANCE.qrveyapp.com https://maps.geo.us-east-1.amazonaws.com https://tiles.openfreemap.orgPermits API calls and WebSocket connections to Qrvey and other supported services.
media-src 'self' data: blob:Allows embedded media content to load from secure sources.
frame-src 'self' blob:Enables blob-based iframes used by some visualizations.
object-src 'none'Blocks plugin content, which Qrvey does not use.
base-uri 'self'Prevents an injected <base> tag from redirecting relative URLs.

Additional Configuration for Design Mode

The base policy above is sufficient for dashboards embedded in Interact mode. Images stored in Qrvey load through your Qrvey instance domain, which is already allowed in img-src.

If you embed dashboards in Design mode, users can add and upload images while editing. Upload requests are made through your Qrvey domain, which redirects to the underlying storage service. CSP is evaluated against the final URL of a redirect requiring your policy to allow the the storage host. It does not suffice to allow only your Qrvey domain.

Add your storage host to connect-src:

connect-src 'self' https://QRVEYINSTANCE.qrveyapp.com wss://QRVEYINSTANCE.qrveyapp.com https://STORAGE_HOST https://maps.geo.us-east-1.amazonaws.com https://tiles.openfreemap.org;
  • AWS (S3) — the user files bucket follows this pattern:

    <accountid><instance>qrveyuserfiles.s3.<region>.amazonaws.com

    For example, a demo instance in us-east-1 under account 003355327446 resolves to:

    003355327446demoqrveyuserfiles.s3.us-east-1.amazonaws.com
  • Azure (Blob Storage) — use the storage account host:

    <account>.blob.core.windows.net

To confirm the exact value for your environment, open your browser's DevTools, go to the Network tab, and upload an image while editing a dashboard. The request to your Qrvey domain displays a redirect. The host of the redirect target is your STORAGE_HOST.

Use the exact host rather than a wildcard such as https://*.s3.us-east-1.amazonaws.com. A wildcard authorizes every S3 bucket in that region, including buckets outside your control.

If a file operation fails, read the console message carefully. It names the storage host, not your Qrvey domain, because the block occurs on the redirect target.

Understanding 'unsafe-inline' for Styles

The style-src directive requires 'unsafe-inline'. Qrvey generates styles programmatically at runtime to support theming, component-level styling, and dynamic visualizations such as sorting and filtering. Some third-party libraries used by the platform do not support nonce-based or hash-based styles.

This is a narrower exposure than 'unsafe-inline' on script-src, which permits arbitrary code execution. The style-src directive governs presentation only. Qrvey has removed the need for 'unsafe-inline' in script-src, closing the code-execution path while retaining inline styles for rendering.

All inline styles are generated internally by Qrvey components and are not derived from user input. Style usage is reviewed as part of Qrvey's ongoing security process.

Validate Your Configuration

Deploy the policy using the Content-Security-Policy-Report-Only header first. The browser reports violations without blocking resources, letting you confirm the configuration against your own application before enforcing it.

Once no violations are reported, switch to the Content-Security-Policy header and verify:

  • document.querySelector('meta[name="csp-nonce"]').content returns a value.
  • That value matches the 'nonce-' value in the Content-Security-Policy response header.
  • After a hard reload, the value has changed. If it has not, the nonce is either being served from cache or is not generated per request, and therefore provides no protection.
  • The browser console reports no CSP violations while loading each widget, including after opening panels, applying filters, and running exports.
  • If you embed in Design mode, upload an image while editing a dashboard. This path involves a redirect to your storage host and is not exercised by testing initial page load alone.

Common Scenarios

SituationExample Adjustment
Using Qrvey-managed instanceReplace QRVEYINSTANCE.qrveyapp.com with the exact domain provided by Qrvey for your environment.
Using custom domainReplace QRVEYINSTANCE.qrveyapp.com with your custom domain (for example, analytics.customerdomain.com).
Strict CSP enforcementEnsure all required Qrvey domains, WebSocket URLs, and optional endpoints are added under their respective directives.