csprefabricate
Version:
Generate valid and secure Content Security Policies (CSP) with TypeScript.
110 lines (109 loc) • 3.66 kB
JavaScript
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;
;