Content Security Policy

MarkupKit gives every page a Content Security Policy it generates from what the site declares: script-src with 'self' for MarkupKit's modules and the controllers, the origin of each declared script, and a hash of each inline head script, plus object-src 'none' and base-uri 'none'. Built pages carry it as a <meta http-equiv="Content-Security-Policy">, and dev and preview also send it as a header. The Markupress theme's script, which applies the saved theme before first paint, is a head script, so its hash is in the policy. The shell, code and outline controllers are modules from the site, so they run under it unchanged.

A script the site adds from another origin, such as analytics, needs that origin. Load it from app/head.js, which MarkupKit inlines and hashes too, and add its origin with MarkupKit's csp option in markupkit.config.ts. A directive such as connect-src, which the generated policy leaves open, needs no entry:

// app/head.js
document.head.append(Object.assign(document.createElement('script'), { src: 'https://analytics.example/script.js', defer: true }));
// markupkit.config.ts
import { defineConfig } from '@threadlabs/markupkit';

export default defineConfig({ csp: { 'script-src': ['https://analytics.example'] } });

The added sources join the generated ones. reportOnly: true in the csp option sends Content-Security-Policy-Report-Only instead, which only a header can, so built pages then carry no policy; csp: false turns it off. dev reports each violation in the terminal and the browser console.

Edit this page

Last updated