Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

helmet

Package Overview
Dependencies
Maintainers
2
Versions
132
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

helmet - npm Package Compare versions

Comparing version 4.2.0 to 4.3.0

10

CHANGELOG.md
# Changelog
## 4.3.0 - 2020-12-27
### Added
- `helmet.contentSecurityPolicy`: setting the `default-src` to `helmet.contentSecurityPolicy.dangerouslyDisableDefaultSrc` disables it
### Changed
- `helmet.frameguard`: slightly improved error messages for non-strings
## 4.2.0 - 2020-11-01

@@ -4,0 +14,0 @@

36

dist/index.js

@@ -21,3 +21,2 @@ "use strict";

}
// This is overly verbose. It'd be nice to condense this while still being type-safe.
if (Object.values(options).some((option) => option === true)) {

@@ -27,24 +26,12 @@ throw new Error("Helmet no longer supports `true` as a middleware option. Remove the property from your options to fix this error.");

const middlewareFunctions = [];
if (options.contentSecurityPolicy === undefined) {
middlewareFunctions.push(content_security_policy_1.default());
}
else if (options.contentSecurityPolicy !== false) {
if (options.contentSecurityPolicy !== false) {
middlewareFunctions.push(content_security_policy_1.default(options.contentSecurityPolicy));
}
if (options.dnsPrefetchControl === undefined) {
middlewareFunctions.push(x_dns_prefetch_control_1.default());
}
else if (options.dnsPrefetchControl !== false) {
if (options.dnsPrefetchControl !== false) {
middlewareFunctions.push(x_dns_prefetch_control_1.default(options.dnsPrefetchControl));
}
if (options.expectCt === undefined) {
middlewareFunctions.push(expect_ct_1.default());
}
else if (options.expectCt !== false) {
if (options.expectCt !== false) {
middlewareFunctions.push(expect_ct_1.default(options.expectCt));
}
if (options.frameguard === undefined) {
middlewareFunctions.push(x_frame_options_1.default());
}
else if (options.frameguard !== false) {
if (options.frameguard !== false) {
middlewareFunctions.push(x_frame_options_1.default(options.frameguard));

@@ -58,6 +45,3 @@ }

}
if (options.hsts === undefined) {
middlewareFunctions.push(strict_transport_security_1.default());
}
else if (options.hsts !== false) {
if (options.hsts !== false) {
middlewareFunctions.push(strict_transport_security_1.default(options.hsts));

@@ -77,12 +61,6 @@ }

}
if (options.permittedCrossDomainPolicies === undefined) {
middlewareFunctions.push(x_permitted_cross_domain_policies_1.default());
}
else if (options.permittedCrossDomainPolicies !== false) {
if (options.permittedCrossDomainPolicies !== false) {
middlewareFunctions.push(x_permitted_cross_domain_policies_1.default(options.permittedCrossDomainPolicies));
}
if (options.referrerPolicy === undefined) {
middlewareFunctions.push(referrer_policy_1.default());
}
else if (options.referrerPolicy !== false) {
if (options.referrerPolicy !== false) {
middlewareFunctions.push(referrer_policy_1.default(options.referrerPolicy));

@@ -89,0 +67,0 @@ }

@@ -8,3 +8,3 @@ /// <reference types="node" />

interface ContentSecurityPolicyDirectives {
[directiveName: string]: Iterable<ContentSecurityPolicyDirectiveValue>;
[directiveName: string]: Iterable<ContentSecurityPolicyDirectiveValue> | typeof dangerouslyDisableDefaultSrc;
}

@@ -15,4 +15,5 @@ export interface ContentSecurityPolicyOptions {

}
declare const dangerouslyDisableDefaultSrc: unique symbol;
declare const getDefaultDirectives: () => {
[x: string]: Iterable<ContentSecurityPolicyDirectiveValue>;
[x: string]: Iterable<ContentSecurityPolicyDirectiveValue> | typeof dangerouslyDisableDefaultSrc;
};

@@ -22,6 +23,7 @@ declare function contentSecurityPolicy(options?: Readonly<ContentSecurityPolicyOptions>): (req: IncomingMessage, res: ServerResponse, next: (err?: Error) => void) => void;

var getDefaultDirectives: () => {
[x: string]: Iterable<ContentSecurityPolicyDirectiveValue>;
[x: string]: Iterable<ContentSecurityPolicyDirectiveValue> | unique symbol;
};
var dangerouslyDisableDefaultSrc: unique symbol;
}
export default contentSecurityPolicy;
export { getDefaultDirectives };
export { getDefaultDirectives, dangerouslyDisableDefaultSrc };
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDefaultDirectives = void 0;
exports.dangerouslyDisableDefaultSrc = exports.getDefaultDirectives = void 0;
const dangerouslyDisableDefaultSrc = Symbol("dangerouslyDisableDefaultSrc");
exports.dangerouslyDisableDefaultSrc = dangerouslyDisableDefaultSrc;
const DEFAULT_DIRECTIVES = {

@@ -19,17 +21,9 @@ "default-src": ["'self'"],

exports.getDefaultDirectives = getDefaultDirectives;
const isRawPolicyDirectiveNameInvalid = (rawDirectiveName) => rawDirectiveName.length === 0 || /[^a-zA-Z0-9-]/.test(rawDirectiveName);
const dashify = (str) => str.replace(/[A-Z]/g, (capitalLetter) => "-" + capitalLetter.toLowerCase());
const isDirectiveValueInvalid = (directiveValue) => /;|,/.test(directiveValue);
const has = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
function getHeaderName({ reportOnly, }) {
if (reportOnly) {
return "Content-Security-Policy-Report-Only";
}
else {
return "Content-Security-Policy";
}
}
function normalizeDirectives(options) {
const result = {};
const { directives: rawDirectives = getDefaultDirectives() } = options;
const result = [];
const directiveNamesSeen = new Set();
for (const rawDirectiveName in rawDirectives) {

@@ -39,9 +33,11 @@ if (!has(rawDirectives, rawDirectiveName)) {

}
if (isRawPolicyDirectiveNameInvalid(rawDirectiveName)) {
if (rawDirectiveName.length === 0 ||
/[^a-zA-Z0-9-]/.test(rawDirectiveName)) {
throw new Error(`Content-Security-Policy received an invalid directive name ${JSON.stringify(rawDirectiveName)}`);
}
const directiveName = dashify(rawDirectiveName);
if (has(result, directiveName)) {
if (directiveNamesSeen.has(directiveName)) {
throw new Error(`Content-Security-Policy received a duplicate directive ${JSON.stringify(directiveName)}`);
}
directiveNamesSeen.add(directiveName);
const rawDirectiveValue = rawDirectives[rawDirectiveName];

@@ -52,2 +48,13 @@ let directiveValue;

}
else if (!rawDirectiveValue) {
throw new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}`);
}
else if (rawDirectiveValue === dangerouslyDisableDefaultSrc) {
if (directiveName === "default-src") {
continue;
}
else {
throw new Error(`Content-Security-Policy: tried to disable ${JSON.stringify(directiveName)} as if it were default-src; simply omit the key`);
}
}
else {

@@ -61,5 +68,8 @@ directiveValue = rawDirectiveValue;

}
result[directiveName] = directiveValue;
result.push({ directiveName, directiveValue });
}
if (!("default-src" in result)) {
if (!result.length) {
throw new Error("Content-Security-Policy has no directives. Either set some or disable the header");
}
if (!directiveNamesSeen.has("default-src")) {
throw new Error("Content-Security-Policy needs a default-src but none was provided");

@@ -69,9 +79,5 @@ }

}
function getHeaderValue(req, res, directives) {
function getHeaderValue(req, res, normalizedDirectives) {
const result = [];
for (const directiveName in directives) {
if (!has(directives, directiveName)) {
continue;
}
const rawDirectiveValue = directives[directiveName];
for (const { directiveName, directiveValue: rawDirectiveValue, } of normalizedDirectives) {
let directiveValue = "";

@@ -110,6 +116,8 @@ for (const element of rawDirectiveValue) {

});
const headerName = getHeaderName(options);
const directives = normalizeDirectives(options);
const headerName = options.reportOnly
? "Content-Security-Policy-Report-Only"
: "Content-Security-Policy";
const normalizedDirectives = normalizeDirectives(options);
return function contentSecurityPolicyMiddleware(req, res, next) {
const result = getHeaderValue(req, res, directives);
const result = getHeaderValue(req, res, normalizedDirectives);
if (result instanceof Error) {

@@ -125,3 +133,4 @@ next(result);

contentSecurityPolicy.getDefaultDirectives = getDefaultDirectives;
contentSecurityPolicy.dangerouslyDisableDefaultSrc = dangerouslyDisableDefaultSrc;
module.exports = contentSecurityPolicy;
exports.default = contentSecurityPolicy;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function parseMaxAge(value) {
if (value === undefined) {
return 0;
}
else if (typeof value === "number" &&
value >= 0 &&
Number.isFinite(value)) {
function parseMaxAge(value = 0) {
if (value >= 0 && Number.isFinite(value)) {
return Math.floor(value);

@@ -17,4 +12,3 @@ }

function getHeaderValueFromOptions(options) {
const directives = [];
directives.push(`max-age=${parseMaxAge(options.maxAge)}`);
const directives = [`max-age=${parseMaxAge(options.maxAge)}`];
if (options.enforce) {

@@ -21,0 +15,0 @@ directives.push("enforce");

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const DEFAULT_MAX_AGE = 180 * 24 * 60 * 60;
function parseMaxAge(value) {
if (value === undefined) {
return DEFAULT_MAX_AGE;
}
else if (typeof value === "number" &&
value >= 0 &&
Number.isFinite(value)) {
function parseMaxAge(value = DEFAULT_MAX_AGE) {
if (value >= 0 && Number.isFinite(value)) {
return Math.floor(value);

@@ -12,0 +7,0 @@ }

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function getHeaderValueFromOptions({ action = "SAMEORIGIN", }) {
action = String(action).toUpperCase();
if (action === "SAME-ORIGIN") {
return "SAMEORIGIN";
const normalizedAction = typeof action === "string" ? action.toUpperCase() : action;
switch (normalizedAction) {
case "SAME-ORIGIN":
return "SAMEORIGIN";
case "DENY":
case "SAMEORIGIN":
return normalizedAction;
case "ALLOW-FROM":
throw new Error("X-Frame-Options no longer supports `ALLOW-FROM` due to poor browser support. See <https://github.com/helmetjs/helmet/wiki/How-to-use-X%E2%80%93Frame%E2%80%93Options's-%60ALLOW%E2%80%93FROM%60-directive> for more info.");
default:
throw new Error(`X-Frame-Options received an invalid action ${JSON.stringify(action)}`);
}
else if (action === "DENY" || action === "SAMEORIGIN") {
return action;
}
else if (action === "ALLOW-FROM") {
throw new Error("X-Frame-Options no longer supports `ALLOW-FROM` due to poor browser support. See <https://github.com/helmetjs/helmet/wiki/How-to-use-X%E2%80%93Frame%E2%80%93Options's-%60ALLOW%E2%80%93FROM%60-directive> for more info.");
}
else {
throw new Error(`X-Frame-Options received an invalid action ${JSON.stringify(action)}`);
}
}

@@ -18,0 +17,0 @@ function xFrameOptions(options = {}) {

@@ -9,3 +9,3 @@ {

"description": "help secure Express/Connect apps with various HTTP headers",
"version": "4.2.0",
"version": "4.3.0",
"keywords": [

@@ -60,16 +60,15 @@ "express",

],
"dependencies": {},
"devDependencies": {
"@types/connect": "^3.4.33",
"@types/jest": "^26.0.15",
"@types/connect": "^3.4.34",
"@types/jest": "^26.0.19",
"@types/supertest": "^2.0.10",
"@typescript-eslint/eslint-plugin": "^4.6.0",
"@typescript-eslint/parser": "^4.6.0",
"@typescript-eslint/eslint-plugin": "^4.11.0",
"@typescript-eslint/parser": "^4.11.0",
"connect": "^3.7.0",
"eslint": "^7.12.1",
"jest": "^26.6.1",
"prettier": "^2.1.2",
"supertest": "^6.0.0",
"ts-jest": "^26.4.3",
"typescript": "^4.0.5"
"eslint": "^7.16.0",
"jest": "^26.6.3",
"prettier": "^2.2.1",
"supertest": "^6.0.1",
"ts-jest": "^26.4.4",
"typescript": "^4.1.3"
},

@@ -76,0 +75,0 @@ "scripts": {

@@ -5,3 +5,2 @@ # Helmet

[![npm dependency status](https://david-dm.org/helmetjs/helmet.svg)](https://david-dm.org/helmetjs/helmet)
[![Build Status](https://travis-ci.org/helmetjs/helmet.svg?branch=master)](https://travis-ci.org/helmetjs/helmet)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fhelmetjs%2Fhelmet.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fhelmetjs%2Fhelmet?ref=badge_shield)

@@ -123,3 +122,3 @@

`options.directives` is an object. Each key is a directive name in camel case (such as `defaultSrc`) or kebab case (such as `default-src`). Each value is an iterable (usually an array) of strings or functions for that directive. If a function appears in the iterable, it will be called with the request and response.
`options.directives` is an object. Each key is a directive name in camel case (such as `defaultSrc`) or kebab case (such as `default-src`). Each value is an iterable (usually an array) of strings or functions for that directive. If a function appears in the iterable, it will be called with the request and response. The `default-src` can be explicitly disabled by setting its value to `helmet.contentSecurityPolicy.dangerouslyDisableDefaultSrc`.

@@ -203,2 +202,12 @@ `options.reportOnly` is a boolean, defaulting to `false`. If `true`, [the `Content-Security-Policy-Report-Only` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only) will be set instead.

);
// Sets "Content-Security-Policy: script-src 'self'"
app.use(
helmet.contentSecurityPolicy({
directives: {
"default-src": helmet.contentSecurityPolicy.dangerouslyDisableDefaultSrc,
"script-src": ["'self'"],
},
})
);
```

@@ -205,0 +214,0 @@

# Security issue reporting & disclosure process
If you feel you have found a security issue or concern with Helmet please reach out to the maintainers.
If you feel you have found a security issue or concern with Helmet, please reach out to the maintainers.

@@ -5,0 +5,0 @@ Email Evan Hahn at <me@evanhahn.com> or Adam Baldwin at <adam@npmjs.com>.

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc