import { escape_html_attr } from '../../../utils/escape.js'; import { base64, sha256 } from './crypto.js'; const array = new Uint8Array(16); function generate_nonce() { crypto.getRandomValues(array); return base64(array); } const quoted = new Set([ 'self', 'unsafe-eval', 'unsafe-hashes', 'unsafe-inline', 'none', 'strict-dynamic', 'report-sample', 'wasm-unsafe-eval', 'script' ]); const crypto_pattern = /^(nonce|sha\d\d\d)-/; // CSP and CSP Report Only are extremely similar with a few caveats // the easiest/DRYest way to express this is with some private encapsulation class BaseProvider { /** @type {boolean} */ #use_hashes; /** @type {boolean} */ #script_needs_csp; /** @type {boolean} */ #style_needs_csp; /** @type {import('types').CspDirectives} */ #directives; /** @type {import('types').Csp.Source[]} */ #script_src; /** @type {import('types').Csp.Source[]} */ #script_src_elem; /** @type {import('types').Csp.Source[]} */ #style_src; /** @type {import('types').Csp.Source[]} */ #style_src_attr; /** @type {import('types').Csp.Source[]} */ #style_src_elem; /** @type {string} */ #nonce; /** * @param {boolean} use_hashes * @param {import('types').CspDirectives} directives * @param {string} nonce */ constructor(use_hashes, directives, nonce) { this.#use_hashes = use_hashes; this.#directives = __SVELTEKIT_DEV__ ? { ...directives } : directives; // clone in dev so we can safely mutate const d = this.#directives; this.#script_src = []; this.#script_src_elem = []; this.#style_src = []; this.#style_src_attr = []; this.#style_src_elem = []; const effective_script_src = d['script-src'] || d['default-src']; const script_src_elem = d['script-src-elem']; const effective_style_src = d['style-src'] || d['default-src']; const style_src_attr = d['style-src-attr']; const style_src_elem = d['style-src-elem']; if (__SVELTEKIT_DEV__) { // remove strict-dynamic in dev... // TODO reinstate this if we can figure out how to make strict-dynamic work // if (d['default-src']) { // d['default-src'] = d['default-src'].filter((name) => name !== 'strict-dynamic'); // if (d['default-src'].length === 0) delete d['default-src']; // } // if (d['script-src']) { // d['script-src'] = d['script-src'].filter((name) => name !== 'strict-dynamic'); // if (d['script-src'].length === 0) delete d['script-src']; // } // ...and add unsafe-inline so we can inject