Skip to main content

Vue Advanced

Content Security Policy

What c15t adds to the page

A Vue app with c15t adds these to the page, and your policy must allow them:

WhatDirective
Requests to your backend's /subjects, plus /init with hosted() or /manifest with manifest({ source: 'runtime' })connect-src
Chunks your build splits out, such as the manifest resolver and the copy for a language other than Englishscript-src 'self'
<script> elements the script loader creates for scriptsscript-src
The inline <script> that consentManifest() adds to index.html to send /init earlyscript-src with a nonce or its hash
Scripts, frames, images and requests your vendors loadscript-src, frame-src, img-src, connect-src for each vendor
The components' CSS, which Vite bundles with your appstyle-src
The <style id="c15t-css-vars"> element with your theme tokens, in <head>style-src
Style bindings, such as the floating trigger's position, set through the CSSOMNone

Allow the backend

Add your backend's origin to connect-src. With a manifestURL or geoURL on another origin, add that origin too. With iab set and an IAB TCF policy, the IAB module fetches the Global Vendor List from the URL the policy gives, usually your backend.

Content-Security-Policy (partial)
connect-src 'self' https://<your-backend-host>;

Use the host from your Inth project or your self-hosted backend.

Allow scripts

The simplest policy lists each vendor's script host in script-src. The integration guide for each vendor names its hosts.

A static Vue app is the same file for every visitor, so it cannot carry a nonce that changes per response. If your server does generate a nonce per response, pass it as the plugin's nonce option. The script loader adds it to every <script> it creates, and a nonce on a single script takes precedence. Scripts that a vendor script loads itself do not get the nonce. Add 'strict-dynamic' to script-src to allow them, or list their hosts.

src/main.ts
app.use(c15tVue, { mode: hosted(), nonce, scripts });

The plugin's nonce option does not reach the early /init script, because that script is already in index.html. With a nonce per response, set Vite's html.cspNonce to a placeholder and have your server replace it with each response's nonce; the script carries it. On a static host, allow the script by the hash in the browser's Refused to execute inline script error. If the policy blocks it, the app sends /init itself.

Allow styles

The components import their CSS, which Vite adds to your app's stylesheet in a production build. style-src 'self' covers it. In development, Vite injects <style> elements, which need 'unsafe-inline' in style-src.

The c15tVue plugin adds your theme tokens to <head> in an inline <style id="c15t-css-vars"> element. A style-src without 'unsafe-inline' blocks it, and the components fall back to the default theme. The element's content is the same for every visitor and only changes when you change tokens, so you can allow it with a hash. Copy the sha256-... value from the browser's Refused to apply inline style console error into style-src, and recompute it whenever you change tokens. When you pass the plugin's nonce option, the element carries that nonce too.

Vue applies the components' style bindings, such as the floating trigger's position, through the CSSOM. A policy does not govern CSSOM changes, so they need no directive.

Verify

Enforce the policy, not report-only, and load the app. The banner shows your token colors, and the console shows no Refused to connect, Refused to load the script or Refused to apply inline style error that mentions your backend, a c15t element or a vendor you allowed. Click Accept All, and the vendor scripts load. The save to /subjects succeeds.