FR EN

CSP and CORS

This is the developer experience win that drove Agreely's design: you can use a strict Content Security Policy without adding unsafe-inline.

Minimal CSP additions

Add these three directives to your existing policy:

script-src  https://cdn.agreely.ca ;
connect-src https://cdn.agreely.ca ;
img-src     https://cdn.agreely.ca ;

That is all. No wildcard. No unsafe-inline, for scripts or styles.

Directive Why
script-src https://cdn.agreely.ca The loader and the banner module are served from this origin.
connect-src https://cdn.agreely.ca The banner fetches configuration and submits consent. The module origin must appear in connect-src because SRI requires a CORS (crossorigin) fetch.
img-src https://cdn.agreely.ca Your company logo (optional) is served from the same domain.

Why no unsafe-inline is needed

The banner styles are applied to the shadow root (Shadow DOM) via a constructable CSSStyleSheet (replaceSync + adoptedStyleSheets). There is no inline <style> element, no inline style attribute, and no eval. A conforming browser that supports Shadow DOM v1 and constructable stylesheets does not need you to loosen your style-src. This design directly answers the problem the founder encountered with a competing solution (Byscuit).

Nonce passthrough

If your script-src is nonce-based rather than host-based, pass your nonce via data-nonce on the loader tag (see Installation). The loader forwards it to the injected module script automatically.

SRI on pinned versions

For security-hardened deployments that pin an exact version, use the versioned URL and verify the published hash in our version manifest:

<script async
  src="https://cdn.agreely.ca/e/v1.2.3/loader.js"
  data-agreely="agr_pub_YOUR_KEY"></script>

Versioned URLs are immutable (Cache-Control: immutable, max-age=31536000) and the loader pins the exact sha384 SRI of the matching build's banner module. The manifest for each version is published at https://cdn.agreely.ca/e/v1.2.3/manifest.json.

No CORS setup required

The public /e/v1/config/{key} endpoint responds with Access-Control-Allow-Origin: * (public configuration, no personal information). The consent submission endpoint (POST /e/v1/consent) uses a text/plain body with no custom headers, making it a simple CORS request: no OPTIONS preflight is issued and no server-side CORS configuration is needed on your end.

In short: you add three lines to your CSP; you configure nothing server-side.

Full policy example

Content-Security-Policy:
  default-src 'self';
  script-src  'self' 'nonce-abc123' https://cdn.agreely.ca https://www.googletagmanager.com;
  connect-src 'self' https://cdn.agreely.ca https://www.google-analytics.com;
  img-src     'self' data: https://cdn.agreely.ca;
  style-src   'self' 'nonce-abc123';
  frame-src   https://www.youtube.com;

Tip: if you also use Google Tag Manager, add https://www.googletagmanager.com to script-src and place the Agreely tag before the GTM tag (see Consent Mode v2).