CSP for iubenda Cookie Consent: Copy-Paste Guide

Table of Contents

If you add iubenda cookie consent to a site with a locked-down Content Security Policy, you’ll usually hit the same wall fast: the banner doesn’t render, scripts stay blocked, or consent updates never reach iubenda.

I’ve dealt with this enough times that I now treat consent managers like any other third-party app: start with a minimal policy, verify every network request, then tighten the policy until it’s boring.

This guide is the practical version for developers. Copy-paste examples first, then the reasoning.

The short version

For iubenda cookie consent, you typically need to allow:

  • script-src for iubenda script hosts
  • style-src for iubenda styles, often including inline styles
  • img-src for assets and tracking pixels
  • connect-src for consent API calls
  • frame-src if iubenda embeds consent-related frames
  • sometimes font-src

The exact hostnames can vary by iubenda product and setup, so always verify in DevTools and CSP reports.

Start with Report-Only first

Don’t ship a fresh CSP change directly in enforcement mode if consent is business-critical.

Use Content-Security-Policy-Report-Only first:

Content-Security-Policy-Report-Only:
  default-src 'self';
  script-src 'self';
  style-src 'self';
  img-src 'self' data:;
  font-src 'self';
  connect-src 'self';
  frame-src 'self';
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'self';
  report-to default-endpoint;

Then watch what iubenda actually needs.

Minimal CSP example for iubenda

This is the baseline I’d start with for a site using iubenda cookie consent and not much else:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://cdn.iubenda.com;
  style-src 'self' 'unsafe-inline' https://cdn.iubenda.com;
  img-src 'self' data: https://cdn.iubenda.com https://www.iubenda.com;
  connect-src 'self' https://cdn.iubenda.com https://www.iubenda.com;
  frame-src 'self' https://www.iubenda.com;
  font-src 'self' https://cdn.iubenda.com;
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'self';

Why this works as a starting point:

  • script-src allows the iubenda loader
  • style-src 'unsafe-inline' is often needed because consent UIs commonly inject inline styles
  • connect-src covers API and consent state calls
  • frame-src is there in case iubenda uses embedded UI or policy content
  • object-src 'none' and base-uri 'self' are easy wins you should keep

Stricter version with nonce support

If your app already uses nonces, use them. I prefer nonces over broad inline allowances whenever the third-party integration supports it cleanly.

Example:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-r4nd0m123' https://cdn.iubenda.com;
  style-src 'self' 'unsafe-inline' https://cdn.iubenda.com;
  img-src 'self' data: https://cdn.iubenda.com https://www.iubenda.com;
  connect-src 'self' https://cdn.iubenda.com https://www.iubenda.com;
  frame-src 'self' https://www.iubenda.com;
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'self';

And your script tag:

<script
  nonce="{{ .CSPNonce }}"
  src="https://cdn.iubenda.com/cs/iubenda_cs.js"
  async>
</script>

If you generate the script tag dynamically in your framework, make sure the nonce is attached to every inline bootstrap script too, not just the external script include.

Most real sites don’t run iubenda alone. They also run Google Tag Manager, analytics, maybe a few pixels. That’s where CSP gets messy.

The real-world policy below, captured from a public header test, shows what a consent-heavy setup often looks like:

content-security-policy:
default-src 'self' https://www.googletagmanager.com https://*.cookiebot.com https://*.google-analytics.com;
script-src 'self' 'nonce-MWIyZDliMDQtMGMyNS00YzRiLThkMTEtOGQ4MTMyNWE2NTgz' 'strict-dynamic' https://www.googletagmanager.com https://*.cookiebot.com https://*.google-analytics.com;
style-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://*.cookiebot.com https://consent.cookiebot.com;
img-src 'self' data: https:;
font-src 'self';
connect-src 'self' https://api.headertest.com https://tallycdn.com https://or.headertest.com wss://or.headertest.com https://*.google-analytics.com https://*.googletagmanager.com https://*.cookiebot.com;
frame-src 'self' https://consentcdn.cookiebot.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
object-src 'none'

That example is for Cookiebot, not iubenda, but it shows the pattern clearly:

  • consent managers usually need multiple directives, not just script-src
  • connect-src is where people forget required hosts
  • frame-src matters more often than expected
  • style-src 'unsafe-inline' is common in these tools, even when I don’t love it

If you want more policy patterns, the ready-to-use examples at https://csp-examples.com are handy for comparison.

Nginx example

add_header Content-Security-Policy "
  default-src 'self';
  script-src 'self' https://cdn.iubenda.com;
  style-src 'self' 'unsafe-inline' https://cdn.iubenda.com;
  img-src 'self' data: https://cdn.iubenda.com https://www.iubenda.com;
  connect-src 'self' https://cdn.iubenda.com https://www.iubenda.com;
  frame-src 'self' https://www.iubenda.com;
  font-src 'self' https://cdn.iubenda.com;
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'self';
" always;

If you’re doing per-request nonces in Nginx, don’t fake it with a static value. Generate them server-side properly.

Apache example

Header always set Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.iubenda.com; style-src 'self' 'unsafe-inline' https://cdn.iubenda.com; img-src 'self' data: https://cdn.iubenda.com https://www.iubenda.com; connect-src 'self' https://cdn.iubenda.com https://www.iubenda.com; frame-src 'self' https://www.iubenda.com; font-src 'self' https://cdn.iubenda.com; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'self';"

Express / Node example

app.use((req, res, next) => {
  res.setHeader(
    "Content-Security-Policy",
    [
      "default-src 'self'",
      "script-src 'self' https://cdn.iubenda.com",
      "style-src 'self' 'unsafe-inline' https://cdn.iubenda.com",
      "img-src 'self' data: https://cdn.iubenda.com https://www.iubenda.com",
      "connect-src 'self' https://cdn.iubenda.com https://www.iubenda.com",
      "frame-src 'self' https://www.iubenda.com",
      "font-src 'self' https://cdn.iubenda.com",
      "object-src 'none'",
      "base-uri 'self'",
      "form-action 'self'",
      "frame-ancestors 'self'"
    ].join("; ")
  );
  next();
});

If you use Helmet, keep the same directive structure:

import helmet from "helmet";

app.use(
  helmet.contentSecurityPolicy({
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "https://cdn.iubenda.com"],
      styleSrc: ["'self'", "'unsafe-inline'", "https://cdn.iubenda.com"],
      imgSrc: ["'self'", "data:", "https://cdn.iubenda.com", "https://www.iubenda.com"],
      connectSrc: ["'self'", "https://cdn.iubenda.com", "https://www.iubenda.com"],
      frameSrc: ["'self'", "https://www.iubenda.com"],
      fontSrc: ["'self'", "https://cdn.iubenda.com"],
      objectSrc: ["'none'"],
      baseUri: ["'self'"],
      formAction: ["'self'"],
      frameAncestors: ["'self'"]
    }
  })
);

Common CSP problems with iubenda

1. The banner script loads, but the UI is broken

Usually style-src is too strict.

Try:

style-src 'self' 'unsafe-inline' https://cdn.iubenda.com;

Yes, I’d prefer not to allow inline styles either. But with consent banners, you often have to choose between theoretical purity and a banner that actually renders.

Usually connect-src is missing a required iubenda endpoint.

Check the browser console for violations like:

Refused to connect to https://www.iubenda.com/... because it violates the following Content Security Policy directive: "connect-src 'self'".

Then add the exact origin.

3. Embedded policy or preferences modal fails

Usually frame-src is missing.

Try:

frame-src 'self' https://www.iubenda.com;

4. Images or icons inside the banner don’t render

Check img-src and font-src.

A safe starting point:

img-src 'self' data: https://cdn.iubenda.com https://www.iubenda.com;
font-src 'self' https://cdn.iubenda.com;

A tighter policy after validation

Once you’ve confirmed what iubenda actually uses on your site, trim it down.

For example, if no fonts or frames are needed:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://cdn.iubenda.com;
  style-src 'self' 'unsafe-inline' https://cdn.iubenda.com;
  img-src 'self' data: https://cdn.iubenda.com;
  connect-src 'self' https://www.iubenda.com;
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'self';

That’s usually where I try to end up: specific hosts, no wildcard unless there’s a real reason, and no extra directives carrying dead entries from old experiments.

Debug checklist

When iubenda breaks under CSP, I go through this list:

  1. Open DevTools console and filter CSP violations.
  2. Check Network for blocked script, XHR/fetch, frame, font, and image requests.
  3. Add missing origins to the correct directive, not just default-src.
  4. Test consent accept/reject flows, not just initial page load.
  5. Test on pages with GTM or marketing tags, because that’s where interactions get weird.
  6. Move from Report-Only to enforced CSP only after the full consent flow works.

Directives I’d keep on almost every site

Even when debugging third-party consent tools, I keep these unless there’s a very good reason not to:

object-src 'none';
base-uri 'self';
form-action 'self';

And for clickjacking protection:

frame-ancestors 'self';

Or, if the site should never be framed:

frame-ancestors 'none';

Official docs worth checking

For the CSP spec and browser behavior, use the official MDN and W3C references:

  • https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
  • https://www.w3.org/TR/CSP3/

For implementation details specific to your iubenda setup, verify against iubenda’s official documentation and the exact network calls your site makes.

The biggest mistake I see is copying a giant third-party CSP allowlist from another site and never validating it. Don’t do that. Start small, inspect real requests, and only allow what your iubenda integration actually needs.