diff --git a/packages/csp-header/src/index.ts b/packages/csp-header/src/index.ts index 2cac6d2..fe3fdd1 100644 --- a/packages/csp-header/src/index.ts +++ b/packages/csp-header/src/index.ts @@ -1,6 +1,9 @@ import { ALLOWED_DIRECTIVES, } from './constants/directives'; +import { + NONE +} from './constants/values'; import { CSPHeaderParams, CSPDirectives, @@ -138,10 +141,18 @@ function mergeDirectiveRules(directiveValue1: CSPDirectiveValue = '', directiveV } if (Array.isArray(directiveValue1) && Array.isArray(directiveValue2)) { - return getUniqRules([ + const uniqRules = getUniqRules([ ...directiveValue1, ...directiveValue2 ]); + + const noneIndex = uniqRules.indexOf(NONE); + // Remove "'none'" if there are other rules + if(noneIndex >= 0 && uniqRules.length > 1) { + uniqRules.splice(noneIndex, 1); + } + + return uniqRules; } return directiveValue2; diff --git a/packages/csp-header/tests/index.test.ts b/packages/csp-header/tests/index.test.ts index f1e872f..7c46b70 100644 --- a/packages/csp-header/tests/index.test.ts +++ b/packages/csp-header/tests/index.test.ts @@ -1,4 +1,4 @@ -import { getCSP, CSPDirectiveName, CSPHeaderParams, nonce, SELF } from '../src'; +import {CSPDirectiveName, CSPHeaderParams, getCSP, nonce, NONE, SELF} from '../src'; describe('CSP building', () => { test('should correctly make policy with the only rule', () => { @@ -107,6 +107,32 @@ describe('Presets', () => { })).toBe('script-src domain1.com domain2.com;') }); + test('should remove \'none\' directive when merging with well-defined directive', () => { + expect(getCSP({ + directives: { + 'script-src': [ 'domain1.com' ] + }, + presets: [ + { + 'script-src': [ NONE ] + } + ] + })).toBe('script-src domain1.com;') + }); + + test('should remove \'none\' directive when merging with well-defined preset', () => { + expect(getCSP({ + directives: { + 'script-src': [ NONE ] + }, + presets: [ + { + 'script-src': [ 'domain2.com' ] + } + ] + })).toBe('script-src domain2.com;') + }); + test('should work with empty policies', () => { expect(getCSP({ directives: {}, @@ -206,6 +232,32 @@ describe('Presets', () => { })).toBe('script-src domain1.com domain2.com;') }); + test('should remove \'none\' directive when merging with well-defined directive', () => { + expect(getCSP({ + directives: { + 'script-src': [ 'domain1.com' ] + }, + presets: { + myPreset: { + 'script-src': [ NONE ] + } + } + })).toBe('script-src domain1.com;') + }); + + test('should remove \'none\' directive when merging with well-defined preset', () => { + expect(getCSP({ + directives: { + 'script-src': [ NONE ] + }, + presets: { + myPreset: { + 'script-src': [ 'domain2.com' ] + } + } + })).toBe('script-src domain2.com;') + }); + test('should work with empty policies', () => { expect(getCSP({ directives: {},