UNPKG

csprefabricate

Version:

Generate valid and secure Content Security Policies (CSP) with TypeScript.

110 lines (109 loc) 3.66 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.formatRule = exports.isValidDirective = void 0; exports.warnOnCspIssues = warnOnCspIssues; const types_1 = require("./types"); const DEFAULT_WARNINGS = { overlyPermissive: true, missingDirectives: true, unsafeInline: true, missingNonceOrHash: true, dataUri: true, }; const validDirectives = [ "default-src", "script-src", "style-src", "img-src", "connect-src", "font-src", "object-src", "media-src", "frame-src", "sandbox", "report-uri", "child-src", "form-action", "frame-ancestors", "plugin-types", "base-uri", "report-to", "worker-src", "manifest-src", "prefetch-src", "navigate-to", "require-trusted-types-for", "trusted-types", "upgrade-insecure-requests", "block-all-mixed-content", ]; const specialRules = [ "none", "self", "unsafe-inline", "unsafe-eval", "strict-dynamic", "unsafe-hashes", ]; function warnOnCspIssues(csp, overrides = {}) { const options = { ...DEFAULT_WARNINGS, ...overrides }; // 1. Overly permissive: * in script-src, style-src, etc. if (options.overlyPermissive) { [ types_1.Directive.SCRIPT_SRC, types_1.Directive.STYLE_SRC, types_1.Directive.IMG_SRC, types_1.Directive.CONNECT_SRC, ].forEach((directive) => { const rules = csp[directive]; if (Array.isArray(rules) && rules.includes("*")) { console.warn(`[CSPrefabricate] Overly permissive: '*' found in ${directive}`); } }); } // 2. Missing important directives if (options.missingDirectives) { [ types_1.Directive.OBJECT_SRC, types_1.Directive.BASE_URI, types_1.Directive.FORM_ACTION, ].forEach((directive) => { if (!(directive in csp)) { console.warn(`[CSPrefabricate] Missing recommended directive: ${directive}`); } }); } // 3. Unsafe inline if (options.unsafeInline) { [types_1.Directive.SCRIPT_SRC, types_1.Directive.STYLE_SRC].forEach((directive) => { const rules = csp[directive]; if (Array.isArray(rules) && rules.includes("'unsafe-inline'")) { console.warn(`[CSPrefabricate] 'unsafe-inline' found in ${directive}`); } }); } // 4. Missing nonce or hash in script-src if 'unsafe-inline' is present if (options.missingNonceOrHash) { const rules = csp[types_1.Directive.SCRIPT_SRC]; if (Array.isArray(rules) && rules.includes("'unsafe-inline'")) { const hasNonceOrHash = rules.some((r) => typeof r === "string" && (r.startsWith("'nonce-") || r.startsWith("'sha"))); if (!hasNonceOrHash) { console.warn(`[CSPrefabricate] 'unsafe-inline' in script-src without nonce or hash`); } } } // 5. Permitting data: in img-src or media-src if (options.dataUri) { [types_1.Directive.IMG_SRC, types_1.Directive.MEDIA_SRC].forEach((directive) => { const rules = csp[directive]; if (Array.isArray(rules) && rules.includes("data:")) { console.warn(`[CSPrefabricate] 'data:' allowed in ${directive}`); } }); } } const isValidDirective = (directive) => validDirectives.includes(directive); exports.isValidDirective = isValidDirective; const formatRule = (rule) => specialRules.includes(rule) ? `'${rule}'` : rule; exports.formatRule = formatRule;