@nasriya/hypercloud
Version:
Nasriya HyperCloud is a lightweight Node.js HTTP2 framework.
90 lines (89 loc) • 6.07 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const helpers_1 = __importDefault(require("../../../utils/helpers"));
class ContentSecurityPolicy {
static #_utils = {
validateDirectives: (directives) => {
// Validate each directive
const isValidDirective = (directive, values) => {
// Define valid values for each directive
const validValues = {
"default-src": new Set(["'self'", "'unsafe-inline'", "'unsafe-eval'", "'none'", 'data:', 'blob:', 'mediastream:', 'filesystem:', 'https:', 'http:', 'ws:', 'wss:', 'ftp:', 'ftps:', 'chrome-extension:', 'moz-extension:', 'safari-extension:', 'webviewprogressproxy:', 'android-webview-video-poster:', 'blob:filesystem:', 'intent:', 'webviewprogressproxy:', 'steam:', 'blob:chrome-extension:', 'resource:']),
"base-uri": new Set(["'self'", 'data:', 'blob:', 'filesystem:', 'https:', 'http:']),
"font-src": new Set(["'self'", "'unsafe-inline'", 'data:', 'blob:', 'https:', 'http:', 'filesystem:', 'intent:', 'webviewprogressproxy:', 'safari-extension:', 'moz-extension:', 'chrome-extension:', 'android-webview-video-poster:', 'android-webview-video-poster:', 'blob:chrome-extension:', 'resource:']),
"form-action": new Set(["'self'", 'data:', 'blob:', 'https:', 'http:', 'chrome-extension:', 'moz-extension:', 'safari-extension:', 'blob:chrome-extension:']),
"frame-ancestors": new Set(["'self'", 'data:', 'blob:', 'https:', 'http:', 'ftp:', 'ftps:', 'chrome-extension:', 'moz-extension:', 'safari-extension:', 'blob:chrome-extension:', 'resource:']),
"img-src": new Set(["'self'", 'data:', 'blob:', 'https:', 'http:', 'ftp:', 'ftps:', 'chrome-extension:', 'moz-extension:', 'safari-extension:', 'blob:chrome-extension:', 'resource:', 'intent:', 'webviewprogressproxy:', 'android-webview-video-poster:']),
"object-src": new Set(["'none'", "'self'", 'data:', 'blob:', 'filesystem:', 'https:', 'http:']),
"script-src": new Set(["'self'", "'unsafe-inline'", "'unsafe-eval'", 'data:', 'blob:', 'https:', 'http:', 'ws:', 'wss:', 'ftp:', 'ftps:', 'chrome-extension:', 'moz-extension:', 'safari-extension:', 'blob:chrome-extension:', 'resource:']),
"script-src-attr": new Set(["'none'"]),
"style-src": new Set(["'self'", "'unsafe-inline'", 'data:', 'blob:', 'https:', 'http:', 'ftp:', 'ftps:', 'chrome-extension:', 'moz-extension:', 'safari-extension:', 'blob:chrome-extension:', 'resource:']),
"upgrade-insecure-requests": new Set([]), // No values allowed
"worker-src": new Set(["'self'", 'data:', 'blob:', 'https:', 'http:', 'ws:', 'wss:', 'ftp:', 'ftps:', 'chrome-extension:', 'moz-extension:', 'safari-extension:', 'blob:chrome-extension:', 'resource:', 'intent:', 'webviewprogressproxy:', 'android-webview-video-poster:']),
"manifest-src": new Set(["'self'", 'data:', 'blob:', 'https:', 'http:', 'ftp:', 'ftps:', 'chrome-extension:', 'moz-extension:', 'safari-extension:', 'blob:chrome-extension:', 'resource:']),
"navigate-to": new Set(["'self'", 'data:', 'blob:', 'https:', 'http:', 'ftp:', 'ftps:', 'chrome-extension:', 'moz-extension:', 'safari-extension:', 'blob:chrome-extension:', 'resource:']),
// Add more valid values for other directives as needed
};
// Check if each value in the directive is valid
for (const value of values) {
if (!validValues[directive]?.has(value)) {
return false; // Invalid value found
}
}
return true; // All values are valid
};
// Validate each directive
for (const directive in directives) {
if (!isValidDirective(directive, directives[directive] || [])) {
return false; // Invalid directive found
}
}
return true; // All directives are valid
}
};
static defaultDirectives = {
"default-src": ["'self'"],
"base-uri": ["'self'"],
"font-src": ["'self'", "https:", "data:"],
"form-action": ["'self'"],
"frame-ancestors": ["'self'"],
"img-src": ["'self'", "data:"],
"object-src": ["'none'"],
"script-src": ["'self'"],
"script-src-attr": ["'none'"],
"style-src": ["'self'", "https:", "'unsafe-inline'"],
"upgrade-insecure-requests": []
};
static defaultOptions = {
useDefaults: false,
directives: ContentSecurityPolicy.defaultDirectives
};
static validate(options) {
const directives = (() => {
if (options === false) {
return ContentSecurityPolicy.defaultDirectives;
}
if (!helpers_1.default.is.undefined(options) && helpers_1.default.is.realObject(options) && options.useDefaults === false) {
// Validate user-provided directives
if (ContentSecurityPolicy.#_utils.validateDirectives(options.directives)) {
// Use provided options if they are valid and useDefaults is explicitly false
return options.directives;
}
else {
throw new Error(`The provided CSP directives are invalid`);
}
}
else {
// Use default directives
return ContentSecurityPolicy.defaultDirectives;
}
})();
return Object.entries(directives)
.map(([key, values]) => `${key} ${(Array.isArray(values) ? values : [values]).join(' ')}`)
.join('; ');
}
}
exports.default = ContentSecurityPolicy;
;