csp-header
Version:
Content-Security-Policy header generator
134 lines • 4.46 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCSP = getCSP;
exports.nonce = nonce;
const directives_1 = require("./constants/directives");
const values_1 = require("./constants/values");
__exportStar(require("./types"), exports);
__exportStar(require("./constants/directives"), exports);
__exportStar(require("./constants/values"), exports);
/**
* Build CSP header value from params
*/
function getCSP(params = {}) {
const { directives = {}, presets = {}, reportUri } = params;
const presetsList = normalizePresetsList(presets);
const mergedPolicies = applyPresets(directives, presetsList);
return policyToString(mergedPolicies, reportUri);
}
/**
* Build CSP nonce string
*/
function nonce(nonceKey) {
return `'nonce-${nonceKey}'`;
}
/**
* Build CSP header value from resolved policy
*/
function policyToString(directives, reportUri) {
const cspStringParts = [];
for (const directiveName in directives) {
if (!directives.hasOwnProperty(directiveName)) {
continue;
}
const directiveValue = directives[directiveName];
if (!directiveValue) {
continue;
}
const directiveRulesString = getDirectiveString(directiveName, directiveValue);
if (directiveRulesString) {
cspStringParts.push(directiveRulesString);
}
}
if (reportUri) {
cspStringParts.push(getReportUriDirective(reportUri));
}
return cspStringParts.join(' ');
}
/**
* Build directive rules part of CSP header value
*/
function getDirectiveString(directiveName, directiveValue) {
if (typeof directiveValue === 'boolean') {
return `${directiveName};`;
}
if (typeof directiveValue === 'string') {
return `${directiveName} ${directiveValue};`;
}
if (Array.isArray(directiveValue)) {
const valueString = directiveValue.join(' ');
return `${directiveName} ${valueString};`;
}
return '';
}
/**
* Build report-uri directive
*/
function getReportUriDirective(reportUri) {
return `report-uri ${reportUri};`;
}
/**
* Normalize different presets list formats to array format
*/
function normalizePresetsList(presets) {
return Array.isArray(presets) ? presets : Object.values(presets);
}
/**
* Merges presets to policy
*/
function applyPresets(directives, presets) {
const mergedPolicies = {};
for (const preset of [directives, ...presets]) {
for (const directiveName in preset) {
if (!(directiveName in directives_1.ALLOWED_DIRECTIVES)) {
continue;
}
const currentRules = mergedPolicies[directiveName];
const presetRules = preset[directiveName];
if (presetRules === undefined) {
continue;
}
mergedPolicies[directiveName] = mergeDirectiveRules(currentRules, presetRules);
}
}
return mergedPolicies;
}
function mergeDirectiveRules(directiveValue1 = '', directiveValue2 = '') {
if (directiveValue1 === undefined) {
return directiveValue2;
}
if (directiveValue2 === undefined) {
return directiveValue1;
}
if (Array.isArray(directiveValue1) && Array.isArray(directiveValue2)) {
const uniqRules = getUniqRules([
...directiveValue1,
...directiveValue2
]);
const noneIndex = uniqRules.indexOf(values_1.NONE);
// Remove "'none'" if there are other rules
if (noneIndex >= 0 && uniqRules.length > 1) {
uniqRules.splice(noneIndex, 1);
}
return uniqRules;
}
return directiveValue2;
}
function getUniqRules(rules) {
return Array.from(new Set(rules));
}
//# sourceMappingURL=index.js.map
;