Nuxt Advanced
Content Security Policy
What c15t adds to the page
A Nuxt app with c15t adds these to the page, and your policy must allow them:
| What | Directive |
|---|---|
The <style id="c15t-css-vars"> tag with your theme tokens, in the page head | style-src |
The components' CSS: inline <style> tags Nuxt writes for the server-rendered banner, and stylesheets Nuxt bundles with your app | style-src |
On ssr: false pages in hosted() mode, an inline <script> in the page head that starts /init | script-src |
On server-rendered pages with a banner, an inline <script> before its buttons that holds a tap made before hydration | script-src |
Browser requests to /api/c15t/init and /api/c15t/manifest in the default manifest() mode | connect-src 'self' |
Consent saves to your backend's /subjects, plus /init in hosted() mode | connect-src |
Chunks Nuxt splits out, such as the browser resolver with manifest({ resolve: 'browser' }) and the copy for a language other than English | script-src 'self' |
<script> elements the script loader creates for scripts | script-src |
| Scripts, frames, images and requests your vendors load | script-src, frame-src, img-src, connect-src for each vendor |
Nuxt adds its own inline scripts and, by default, inline styles. Its
documentation and modules such as nuxt-security cover those. The banner's
first paint uses Nuxt's inline styles. If your policy cannot allow them, turn
them off with features: { inlineStyles: false } in nuxt.config.ts: Nuxt
then links the banner's CSS as stylesheets, and the module leaves those links
in place.
Allow the theme token style tag
The module writes the tokens option into an inline
<style id="c15t-css-vars"> tag on every page. A style-src without
'unsafe-inline' blocks it, and the banner falls back to the default theme. The tag's content
is the same for every visitor and only changes when you change tokens, so
you can allow it with a hash:
- Load a page with the policy enforced.
- Copy the
sha256-...value from the browser'sRefused to apply inline styleconsole error. - Add it to
style-srcand redeploy.
Recompute the hash whenever you change tokens. When you set the module's
nonce option, the tag carries that nonce, so a style-src that lists the
same nonce allows it. When your policy already allows 'unsafe-inline' for
Nuxt's own styles, the tag needs nothing more.
Allow the early init script
On a page with ssr: false in hosted() mode, the module writes an inline
<script> into the page head that requests your backend's /init before the
app's JavaScript loads. A script-src without 'unsafe-inline' blocks it, and
the app then sends its own /init request after it loads, as it would without
the script.
- With
nuxt-security, the script carries its per-request nonce. Nothing more is needed. - With the module's
nonceoption, the script carries that nonce. - With a hash-based policy, the script's content is the same for every
visitor and changes only when you change
backendURLor upgrade c15t. Copy thesha256-...value from the browser'sRefused to execute inline scriptconsole error and add it toscript-src.
To leave the script out, set initPrefetch: false in the module options.
A server-rendered banner also writes an inline <script> before its buttons.
It holds a tap the visitor makes before the app hydrates. It carries the
module's nonce option when set, and its content is the same for every
visitor, so a hash works too. If your policy blocks it, the banner still works
after hydration, but a tap before then does nothing.
Allow the backend
In the default manifest() mode the browser calls your own origin for
/api/c15t/init, which 'self' covers, and sends consent saves to your
backend. Add the backend's origin to connect-src. A manifestURL or
geoURL on another origin needs that origin too. With iab set and an IAB
TCF policy, the browser loads the Global Vendor List through the module's
consent route in manifest() mode, or from your backend otherwise.
Use the host from your Inth project or your self-hosted backend. Requests the Nuxt server makes during rendering are not subject to the browser's policy.
Allow scripts
List each vendor's script host in script-src. The
integration guide for each vendor names its
hosts.
The module's nonce option adds a nonce to every script the loader creates.
Module options and app.config.ts are fixed when the app builds, so every
response gets the same value. A nonce only protects a page when it changes on
each response, so prefer the host allowlist for c15t's scripts.
Verify
Enforce the policy, not report-only, and load a page. The banner shows your
token colors, and the console shows no Refused to apply inline style,
Refused to connect or Refused to load the script error that mentions a
c15t element, your backend or a vendor you allowed. Click Accept All, and the
vendor scripts load. The save to /subjects succeeds.