@nasriya/hypercloud
Version:
Nasriya HyperCloud is a lightweight Node.js HTTP2 framework.
285 lines (284 loc) • 13.7 kB
JavaScript
import helpers from "../../utils/helpers.js";
// Headers
import ContentSecurityPolicy from './assets/contentSecurityPolicy.js';
import CrossOriginEmbedderPolicy from "./assets/crossOriginEmbedderPolicy.js";
import CrossOriginOpenerPolicy from "./assets/crossOriginOpenerPolicy.js";
import CrossOriginResourcePolicy from "./assets/crossOriginResourcePolicy.js";
import ReferrerPolicy from "./assets/referrerPolicy.js";
import StrictTransportSecurity from "./assets/strictTransportSecurity.js";
import DNSPrefetchControl from "./assets/xDnsPrefetchControl.js";
import XFrameOptions from "./assets/xFrameOptions.js";
import XPermittedCrossDomainPolicies from "./assets/xPermittedCrossDomainPolicies.js";
class HelmetManager {
#_server;
#_defaults = {
values: {
contentSecurityPolicy: "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",
crossOriginEmbedderPolicy: 'require-corp',
crossOriginOpenerPolicy: 'same-origin',
crossOriginResourcePolicy: 'same-origin',
originAgentCluster: '?1',
referrerPolicy: 'no-referrer',
strictTransportSecurity: 'max-age=31536000; includeSubDomains; preload',
xContentTypeOptions: 'nosniff',
xDnsPrefetchControl: 'off',
xDownloadOptions: 'noopen',
xFrameOptions: 'DENY',
xPermittedCrossDomainPolicies: 'none',
xPoweredBy: true,
xXssProtection: true
}
};
#_values = {
contentSecurityPolicy: '',
crossOriginEmbedderPolicy: '',
crossOriginOpenerPolicy: '',
crossOriginResourcePolicy: '',
originAgentCluster: '',
referrerPolicy: '',
strictTransportSecurity: '',
xContentTypeOptions: '',
xDnsPrefetchControl: '',
xDownloadOptions: '',
xFrameOptions: '',
xPermittedCrossDomainPolicies: '',
xPoweredBy: true,
xXssProtection: true
};
constructor(server) {
this.#_server = server;
this.#_values.contentSecurityPolicy = this.#_defaults.values.contentSecurityPolicy;
this.#_values.crossOriginEmbedderPolicy = this.#_defaults.values.crossOriginEmbedderPolicy;
this.#_values.crossOriginOpenerPolicy = this.#_defaults.values.crossOriginOpenerPolicy;
this.#_values.crossOriginResourcePolicy = this.#_defaults.values.crossOriginResourcePolicy;
this.#_values.originAgentCluster = this.#_defaults.values.originAgentCluster;
this.#_values.referrerPolicy = this.#_defaults.values.referrerPolicy;
this.#_values.strictTransportSecurity = this.#_defaults.values.strictTransportSecurity;
this.#_values.xContentTypeOptions = this.#_defaults.values.xContentTypeOptions;
this.#_values.xDnsPrefetchControl = this.#_defaults.values.xDnsPrefetchControl;
this.#_values.xDownloadOptions = this.#_defaults.values.xDownloadOptions;
this.#_values.xFrameOptions = this.#_defaults.values.xFrameOptions;
this.#_values.xPermittedCrossDomainPolicies = this.#_defaults.values.xPermittedCrossDomainPolicies;
this.#_values.xPoweredBy = this.#_defaults.values.xPoweredBy;
this.#_values.xXssProtection = this.#_defaults.values.xXssProtection;
}
/**
* Setup a protection helmet for your server. You can customize each section
* according to your needs.
* @param options Helmet configuration options
*/
config(options) {
const notUndefined = !helpers.is.undefined(options);
const isRealObject = helpers.is.realObject(options);
// #1: Content-Security-Policy
if (notUndefined && isRealObject && 'contentSecurityPolicy' in options) {
if (options.contentSecurityPolicy === false) {
this.#_values.contentSecurityPolicy = '';
}
else {
this.#_values.contentSecurityPolicy = ContentSecurityPolicy.validate(options.contentSecurityPolicy);
}
}
else {
this.#_values.contentSecurityPolicy = this.#_defaults.values.contentSecurityPolicy;
}
// #2: Cross-Origin-Embedder-Policy
if (notUndefined && isRealObject && 'crossOriginEmbedderPolicy' in options) {
if (options.crossOriginEmbedderPolicy === false) {
this.#_values.crossOriginEmbedderPolicy = '';
}
else {
this.#_values.crossOriginEmbedderPolicy = CrossOriginEmbedderPolicy.validate(options.crossOriginEmbedderPolicy) || '';
}
}
else {
this.#_values.crossOriginEmbedderPolicy = this.#_defaults.values.crossOriginEmbedderPolicy;
}
// #3: Cross-Origin-Opener-Policy
if (notUndefined && isRealObject && 'crossOriginOpenerPolicy' in options) {
if (options.crossOriginOpenerPolicy === false) {
this.#_values.crossOriginOpenerPolicy = '';
}
else {
this.#_values.crossOriginOpenerPolicy = CrossOriginOpenerPolicy.validate(options.crossOriginOpenerPolicy) || '';
}
}
else {
this.#_values.crossOriginOpenerPolicy = this.#_defaults.values.crossOriginOpenerPolicy;
}
// #4: Cross-Origin-Resource-Policy
if (notUndefined && isRealObject && 'crossOriginResourcePolicy' in options) {
if (options.crossOriginResourcePolicy === false) {
this.#_values.crossOriginResourcePolicy = '';
}
else {
this.#_values.crossOriginResourcePolicy = CrossOriginResourcePolicy.validate(options.crossOriginResourcePolicy) || '';
}
}
else {
this.#_values.crossOriginResourcePolicy = this.#_defaults.values.crossOriginResourcePolicy;
}
// #5: Origin-Agent-Cluster
if (notUndefined && isRealObject && 'originAgentCluster' in options) {
if (options.originAgentCluster === false) {
this.#_values.crossOriginResourcePolicy = '';
}
else {
this.#_values.crossOriginResourcePolicy = options.originAgentCluster === '?1' ? options.originAgentCluster : this.#_defaults.values.crossOriginResourcePolicy;
}
}
else {
this.#_values.crossOriginResourcePolicy = this.#_defaults.values.crossOriginResourcePolicy;
}
// #6: Referrer-Policy
if (notUndefined && isRealObject && 'referrerPolicy' in options) {
if (options.referrerPolicy === false) {
this.#_values.referrerPolicy = '';
}
else {
this.#_values.referrerPolicy = ReferrerPolicy.validate(options.referrerPolicy) || '';
}
}
else {
this.#_values.referrerPolicy = this.#_defaults.values.referrerPolicy;
}
// #7: Strict-Transport-Security
if (notUndefined && isRealObject && 'strictTransportSecurity' in options) {
if (options.strictTransportSecurity === false) {
this.#_values.strictTransportSecurity = '';
}
else {
this.#_values.strictTransportSecurity = StrictTransportSecurity.validate(options.strictTransportSecurity) || '';
}
}
else {
this.#_values.strictTransportSecurity = this.#_defaults.values.strictTransportSecurity;
}
// #8: X-Content-Type-Options
if (notUndefined && isRealObject && 'xContentTypeOptions' in options) {
if (options.xContentTypeOptions === false) {
this.#_values.strictTransportSecurity = '';
}
else {
this.#_values.xContentTypeOptions = this.#_defaults.values.xContentTypeOptions;
}
}
else {
this.#_values.xContentTypeOptions = this.#_defaults.values.xContentTypeOptions;
}
// #9: X-DNS-Prefetch-Control
if (notUndefined && isRealObject && 'xDnsPrefetchControl' in options) {
this.#_values.xDnsPrefetchControl = DNSPrefetchControl.validate(options.xDnsPrefetchControl) || '';
}
else {
this.#_values.xDnsPrefetchControl = this.#_defaults.values.xDnsPrefetchControl;
}
// #10: X-Download-Options
if (notUndefined && isRealObject && 'xDownloadOptions' in options && options.xDownloadOptions !== true) {
this.#_values.xDownloadOptions = '';
}
else {
this.#_values.xDownloadOptions = this.#_defaults.values.xDownloadOptions;
}
// #11: X-Frame-Options
if (notUndefined && isRealObject && 'xFrameOptions' in options) {
this.#_values.xFrameOptions = XFrameOptions.validate(options.xFrameOptions) || '';
}
else {
this.#_values.xFrameOptions = this.#_defaults.values.xFrameOptions;
}
// #12: X-Permitted-Cross-Domain-Policies
if (notUndefined && isRealObject && 'xPermittedCrossDomainPolicies' in options) {
this.#_values.xPermittedCrossDomainPolicies = XPermittedCrossDomainPolicies.validate(options.xPermittedCrossDomainPolicies) || '';
}
else {
this.#_values.xPermittedCrossDomainPolicies = this.#_defaults.values.xPermittedCrossDomainPolicies;
}
// #13: X-Powered-By
if (notUndefined && isRealObject && 'xPoweredBy' in options) {
this.#_values.xPoweredBy = typeof options.xPoweredBy === 'boolean' ? options.xPoweredBy : true;
}
else {
this.#_values.xPoweredBy = this.#_defaults.values.xPoweredBy;
}
// #14: X-XSS-Protection
if (notUndefined && isRealObject && 'xXssProtection' in options) {
this.#_values.xXssProtection = typeof options.xXssProtection === 'boolean' ? options.xXssProtection : true;
}
else {
this.#_values.xXssProtection = this.#_defaults.values.xXssProtection;
}
this.#_updateHandler();
}
/**This method updates the handler that is used in every request */
#_updateHandler() {
const handler = (req, res, next) => {
try {
// #1: Content-Security-Policy
if (this.#_values.contentSecurityPolicy) {
res.setHeader('Content-Security-Policy', this.#_values.contentSecurityPolicy);
}
// #2: Cross-Origin-Embedder-Policy
if (this.#_values.crossOriginEmbedderPolicy) {
res.setHeader("Cross-Origin-Embedder-Policy", this.#_values.crossOriginEmbedderPolicy);
}
// #3: Cross-Origin-Opener-Policy
if (this.#_values.crossOriginOpenerPolicy) {
res.setHeader("Cross-Origin-Opener-Policy", this.#_values.crossOriginOpenerPolicy);
}
// #4: Cross-Origin-Resource-Policy
if (this.#_values.crossOriginResourcePolicy) {
res.setHeader("Cross-Origin-Resource-Policy", this.#_values.crossOriginResourcePolicy);
}
// #5: Origin-Agent-Cluster
if (this.#_values.originAgentCluster) {
res.setHeader("Origin-Agent-Cluster", this.#_values.crossOriginResourcePolicy);
}
// #6: Referrer-Policy
if (this.#_values.referrerPolicy) {
res.setHeader("Referrer-Policy", this.#_values.referrerPolicy);
}
// #7: Strict-Transport-Security
if (this.#_values.strictTransportSecurity) {
res.setHeader("Strict-Transport-Security", this.#_values.strictTransportSecurity);
}
// #8: X-Content-Type-Options
if (this.#_values.xContentTypeOptions) {
res.setHeader("X-Content-Type-Options", this.#_values.xContentTypeOptions);
}
// #9: X-DNS-Prefetch-Control
if (this.#_values.xDnsPrefetchControl) {
res.setHeader("X-DNS-Prefetch-Control", this.#_values.xDnsPrefetchControl);
}
// #10: X-Download-Options
if (this.#_values.xDownloadOptions) {
res.setHeader("X-Download-Options", this.#_values.xDownloadOptions);
}
// #11: X-Frame-Options
if (this.#_values.xFrameOptions) {
res.setHeader("X-Frame-Options", this.#_values.xFrameOptions);
}
// #12: X-Permitted-Cross-Domain-Policies
if (this.#_values.xPermittedCrossDomainPolicies) {
res.setHeader("X-Permitted-Cross-Domain-Policies", this.#_values.xPermittedCrossDomainPolicies);
}
// #13: X-Powered-By
if (this.#_values.xPoweredBy) {
res.removeHeader("X-Powered-By");
}
// #14: X-XSS-Protection
if (this.#_values.xXssProtection) {
res.setHeader("X-XSS-Protection", '0');
}
}
catch (error) {
console.error(error);
}
finally {
next();
}
};
this.#_server._handlers.helmet = handler;
}
}
export default HelmetManager;