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-srcfor iubenda script hostsstyle-srcfor iubenda styles, often including inline stylesimg-srcfor assets and tracking pixelsconnect-srcfor consent API callsframe-srcif 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-srcallows the iubenda loaderstyle-src 'unsafe-inline'is often needed because consent UIs commonly inject inline stylesconnect-srccovers API and consent state callsframe-srcis there in case iubenda uses embedded UI or policy contentobject-src 'none'andbase-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.
Example for a site using GTM + consent tooling
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-srcis where people forget required hostsframe-srcmatters more often than expectedstyle-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.
2. Consent choices don’t persist
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:
- Open DevTools console and filter CSP violations.
- Check Network for blocked script, XHR/fetch, frame, font, and image requests.
- Add missing origins to the correct directive, not just
default-src. - Test consent accept/reject flows, not just initial page load.
- Test on pages with GTM or marketing tags, because that’s where interactions get weird.
- 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/CSPhttps://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.