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

express-csp-header

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

express-csp-header - npm Package Compare versions

Comparing version 1.2.1 to 2.0.0

.editorconfig

64

index.js

@@ -7,64 +7,32 @@ var cspHeader = require('csp-header');

function expressCsp(params){
var policies,
extend,
reportUri,
reportOnly;
function expressCsp(params) {
params = params || {};
policies = params.policies;
extend = params.extend;
reportUri = params.reportUri;
reportOnly = Boolean(params.reportOnly);
if(typeof extend === 'object'){
policies = extendPolicies(policies, extend);
}
return function (req, res, next) {
const cspHeaderParams = {
policies: params.policies,
extend: params.extend,
presets: params.presets,
'report-uri': (typeof params.reportUri === 'function' ? params.reportUri(req, res) : params.reportUri)
};
let cspString = cspHeader(cspHeaderParams);
return function(req, res, next){
var cspString = cspHeader({
policies: policies,
'report-uri': (typeof reportUri === 'function' ? reportUri(req, res) : reportUri)
});
if(cspString){
if(cspString.indexOf(expressCsp.NONCE) > -1){
if (cspString) {
if (cspString.indexOf(expressCsp.NONCE) > -1) {
req.nonce = crypto.randomBytes(16).toString('base64');
cspString = cspString.replace(new RegExp(expressCsp.NONCE, 'g'), cspHeader.nonce(req.nonce));
}
if(cspString.indexOf(expressCsp.TLD) > -1){
if (cspString.indexOf(expressCsp.TLD) > -1) {
var domain = parseDomain(req.hostname || req.host);
var tld = domain && domain.tld;
if(tld){
if (tld) {
cspString = cspString.replace(new RegExp(expressCsp.TLD, 'g'), tld);
}
}
res.set(CSP_HEADER_NAME + (reportOnly ? CSP_REPORT_ONLY : ''), cspString);
res.set(CSP_HEADER_NAME + (params.reportOnly ? CSP_REPORT_ONLY : ''), cspString);
next();
}
}
};
}
function extendPolicies(original, extension){
var extended = Object.assign(original);
Object.keys(extension).forEach(function(policyName){
var extPolicy = extension[policyName],
origPolicy = original[policyName];
if(!(extPolicy instanceof Array)){
throw new Error('');
}
if(typeof origPolicy !== 'undefined'){
extPolicy.forEach(function(rule){
if(typeof rule === 'string' && origPolicy.indexOf(rule) === -1){
extended[policyName].push(rule);
}
});
}else{
extended[policyName] = extPolicy;
}
});
return extended;
}
expressCsp.SELF = cspHeader.SELF;

@@ -77,2 +45,2 @@ expressCsp.INLINE = cspHeader.INLINE;

module.exports = expressCsp;
module.exports = expressCsp;
{
"name": "express-csp-header",
"version": "1.2.1",
"version": "2.0.0",
"description": "Content-Security-Policy middleware for Express",

@@ -10,3 +10,3 @@ "main": "index.js",

"scripts": {
"test": "mocha test --check-leaks"
"test": "ava"
},

@@ -24,2 +24,5 @@ "repository": {

"license": "WTFPL",
"engines": {
"node": ">=4"
},
"bugs": {

@@ -30,9 +33,8 @@ "url": "https://github.com/frux/express-csp/issues"

"devDependencies": {
"mocha": "^2.4.5",
"should": "^8.3.0"
"ava": "^0.18.2"
},
"dependencies": {
"csp-header": "^0.0.4",
"csp-header": "^1.0.0",
"parse-domain": "^0.2.1"
}
}

@@ -98,3 +98,3 @@ # Content-Security-Policy middleware for Express

}));
// express will send header with a random nonce key "Content-Security-Policy: script-src 'self'; report-uri https://cspreport.com/send;"
// express will send header "Content-Security-Policy: script-src 'self'; report-uri https://cspreport.com/send;"
```

@@ -113,3 +113,3 @@

}));
// express will send header with a random nonce key "Content-Security-Policy: script-src 'self'; report-uri https://cspreport.com/send?time=1460467355592;"
// express will send header "Content-Security-Policy: script-src 'self'; report-uri https://cspreport.com/send?time=1460467355592;"
```

@@ -119,5 +119,8 @@

#### v1.1.1
#### v1.2.1
* fix leaking to global scope by [@i-akhmadullin](https://github.com/i-akhmadullin)
#### v1.2.0
* new csp-header with CSP 3
#### v1.1.0

@@ -124,0 +127,0 @@ * Policies extending

@@ -1,140 +0,106 @@

var should = require('should'),
expressCsp = require('../'),
mockApp = {
use: function(middleware, req, res){
var req = req || {},
res = res || {
headers: {},
set: function(headerName, headerVal){
this.headers[headerName] = headerVal;
}
};
middleware(req, res, function(){});
return {req: req, res: res};
}
};
import test from 'ava';
import expressCsp from '../';
describe('General', function(){
it('should sets CSP header', function(){
var actual = mockApp.use(expressCsp({
policies: {
'default-src': [ expressCsp.SELF ],
'script-src': [ expressCsp.SELF, expressCsp.INLINE, 'somehost.com' ],
'style-src': [ expressCsp.SELF, 'mystyles.net' ],
'img-src': [ 'data:', 'images.com' ],
'worker-src': [ expressCsp.NONE ],
'block-all-mixed-content': true
const mockApp = {
use(middleware, req, res) {
req = req || {};
res = res || {
headers: {},
set(headerName, headerVal) {
this.headers[headerName] = headerVal;
}
}));
actual.res.headers['Content-Security-Policy'].should.be.equal("default-src 'self'; script-src 'self' 'unsafe-inline' somehost.com; style-src 'self' mystyles.net; img-src data: images.com; worker-src 'none'; block-all-mixed-content;");
});
};
middleware(req, res, () => {});
return {req, res};
}
};
it('should generates nonce key', function(){
var actual = mockApp.use(expressCsp({
policies: {
'script-src': [ expressCsp.NONCE ]
}
}));
test('should sets CSP header', t => {
const actual = mockApp.use(expressCsp({
policies: {
'default-src': [expressCsp.SELF],
'script-src': [expressCsp.SELF, expressCsp.INLINE, 'somehost.com'],
'style-src': [expressCsp.SELF, 'mystyles.net'],
'img-src': ['data:', 'images.com'],
'worker-src': [expressCsp.NONE],
'block-all-mixed-content': true
}
}));
const expected = "default-src 'self'; script-src 'self' 'unsafe-inline' somehost.com; style-src 'self' mystyles.net; img-src data: images.com; worker-src 'none'; block-all-mixed-content;";
/^script\-src \'nonce\-.+\'\;/.test(actual.res.headers['Content-Security-Policy']).should.be.ok();
actual.req.nonce.should.be.type('string');
});
t.is(actual.res.headers['Content-Security-Policy'], expected);
});
it('should adds report-uri param as string', function(){
var actual = mockApp.use(expressCsp({
policies: { 'script-src': [ expressCsp.SELF ] },
reportUri: 'https://cspreport.com'
}));
test('Nonce', t => {
const actual = mockApp.use(expressCsp({
policies: {
'script-src': [expressCsp.NONCE]
}
}));
/report\-uri https\:\/\/cspreport\.com\;$/.test(actual.res.headers['Content-Security-Policy']).should.be.ok();
});
t.true(/^script-src 'nonce-.+';/.test(actual.res.headers['Content-Security-Policy']));
t.is(typeof actual.req.nonce, 'string');
});
it('should adds report-uri param as function', function(){
var actual = mockApp.use(expressCsp({
policies: {
'script-src': [ expressCsp.SELF ]
},
reportUri: function(req, res){
return 'https://cspreport.com/send?time=' + Number(new Date());
}
}));
test('report-uri | string', t => {
const actual = mockApp.use(expressCsp({
policies: {'script-src': [expressCsp.SELF]},
reportUri: 'https://cspreport.com'
}));
/report\-uri https\:\/\/cspreport\.com\/send\?time\=[0-9]+\;$/.test(actual.res.headers['Content-Security-Policy']).should.be.ok();
});
t.is(actual.res.headers['Content-Security-Policy'], "script-src 'self'; report-uri https://cspreport.com;");
});
it('should replace tld', function(){
var actual = mockApp.use(expressCsp({
test('report-uri | function', t => {
const actual = mockApp.use(expressCsp({
policies: {
'script-src': [expressCsp.SELF]
},
reportUri() {
return 'https://cspreport.com/send?time=' + Number(new Date());
}
}));
t.true(/^script-src\s'self';\sreport-uri\shttps:\/\/cspreport\.com\/send\?time=[0-9]+;$/.test(actual.res.headers['Content-Security-Policy']));
});
test('tld', t => {
const actual = mockApp.use(
expressCsp({
policies: {
'script-src': [ 'myhost.' + expressCsp.TLD ]
'script-src': ['myhost.' + expressCsp.TLD]
}
}), {
}),
{
hostname: 'example.com'
});
}
);
actual.res.headers['Content-Security-Policy'].should.be.equal('script-src myhost.com;');
});
t.is(actual.res.headers['Content-Security-Policy'], 'script-src myhost.com;');
});
it('shouldn\'t replace tld if tld is not defined', function(){
var actual = mockApp.use(expressCsp({
test('tld | req.tld is undefined', t => {
const actual = mockApp.use(
expressCsp({
policies: {
'script-src': [ 'myhost.' + expressCsp.TLD ]
'script-src': ['myhost.' + expressCsp.TLD]
}
}), {
}),
{
hostname: 'localhost'
});
}
);
actual.res.headers['Content-Security-Policy'].should.be.equal('script-src myhost.%tld%;');
});
t.is(actual.res.headers['Content-Security-Policy'], 'script-src myhost.%tld%;');
});
it('should supports Report-Only mode', function(){
var actual = mockApp.use(expressCsp({
policies: {
'script-src': [ 'myhost.com' ]
},
reportOnly: true
}));
test('Report-Only', t => {
const actual = mockApp.use(expressCsp({
policies: {
'script-src': ['myhost.com']
},
reportOnly: true
}));
actual.res.headers['Content-Security-Policy-Report-Only'].should.be.equal('script-src myhost.com;');
});
t.is(actual.res.headers['Content-Security-Policy-Report-Only'], 'script-src myhost.com;');
});
describe('Extending', function(){
it('should extend existing policy', function(){
var actual = mockApp.use(expressCsp({
policies: {
'script-src': [ 'myhost.com' ]
},
extend: {
'script-src': [ 'additional.host.com' ]
}
}));
actual.res.headers['Content-Security-Policy'].should.be.equal('script-src myhost.com additional.host.com;');
});
it('shouldn\'t duplicate rule', function(){
var actual = mockApp.use(expressCsp({
policies: {
'script-src': [ 'myhost.com' ]
},
extend: {
'script-src': [ 'myhost.com' ]
}
}));
actual.res.headers['Content-Security-Policy'].should.be.equal('script-src myhost.com;');
});
it('should add new policy', function(){
var actual = mockApp.use(expressCsp({
policies: {
'script-src': [ 'myhost.com' ]
},
extend: {
'style-src': [ 'newhost.com' ]
}
}));
actual.res.headers['Content-Security-Policy'].should.be.equal('script-src myhost.com; style-src newhost.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