From 27b0c2af3b88fb12d1431d78ec332946167afb11 Mon Sep 17 00:00:00 2001 From: Romain Bastide Date: Sat, 6 Apr 2019 02:13:50 +0200 Subject: [PATCH 1/7] Add missing directives in CSP --- src/Header/ContentSecurityPolicy.php | 16 +++++++- test/Header/ContentSecurityPolicyTest.php | 50 +++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/Header/ContentSecurityPolicy.php b/src/Header/ContentSecurityPolicy.php index cc30acd3d2..7b3470d0a0 100644 --- a/src/Header/ContentSecurityPolicy.php +++ b/src/Header/ContentSecurityPolicy.php @@ -8,7 +8,7 @@ namespace Zend\Http\Header; /** - * Content Security Policy 1.0 Header + * Content Security Policy Level 3 Header * * @link http://www.w3.org/TR/CSP/ */ @@ -32,6 +32,20 @@ class ContentSecurityPolicy implements MultipleHeaderInterface 'connect-src', 'sandbox', 'report-uri', + 'child-src', + 'manifest-src', + 'worker-src', + 'prefetch-src', + 'script-src-elem', + 'script-src-attr', + 'style-src-elem', + 'style-src-attr', + 'base-uri', + 'plugin-types', + 'form-action', + 'frame-ancestors', + 'navigate-to', + 'report-to' ]; /** diff --git a/test/Header/ContentSecurityPolicyTest.php b/test/Header/ContentSecurityPolicyTest.php index 837bf2f76c..430b3990e8 100644 --- a/test/Header/ContentSecurityPolicyTest.php +++ b/test/Header/ContentSecurityPolicyTest.php @@ -187,4 +187,54 @@ public function testMultiple() $headers->toString() ); } + + /** + * @dataProvider directivesProvider + * + * @param string $directive + * @param string[] $value + * @param string $expected + */ + public function testContentSecurityPolicySetDirectiveThrowsExceptionIfMissingDirectiveNameGiven( + $directive, + array $value, + $expected + ) { + $csp = new ContentSecurityPolicy(); + $csp->setDirective($directive, $value); + + self::assertSame($expected, $csp->toString()); + } + + public static function directivesProvider() + { + return [ + ['child-src', ["'self'"],"Content-Security-Policy: child-src 'self';"], + ['manifest-src', ["'self'"], "Content-Security-Policy: manifest-src 'self';"], + ['worker-src', ["'self'"], "Content-Security-Policy: worker-src 'self';"], + ['prefetch-src', ["'self'"], "Content-Security-Policy: prefetch-src 'self';"], + ['script-src-elem', ["'self'"], "Content-Security-Policy: script-src-elem 'self';"], + ['script-src-attr', ["'self'"], "Content-Security-Policy: script-src-attr 'self';"], + ['style-src-elem', ["'self'"], "Content-Security-Policy: style-src-elem 'self';"], + ['style-src-attr', ["'self'"], "Content-Security-Policy: style-src-attr 'self';"], + ['base-uri', ["'self'", "'unsafe-inline'"], "Content-Security-Policy: base-uri 'self' 'unsafe-inline';"], + ['plugin-types', ['text/csv'], 'Content-Security-Policy: plugin-types text/csv;'], + ['form-action', + [ + 'http://*.example.com', + "'self'" + ], + "Content-Security-Policy: form-action http://*.example.com 'self';" + ], + ['frame-ancestors', + [ + 'http://*.example.com', + "'self'" + ], + "Content-Security-Policy: frame-ancestors http://*.example.com 'self';" + ], + ['navigate-to', ['example.com'], 'Content-Security-Policy: navigate-to example.com;'], + ['sandbox', ['allow-forms'], 'Content-Security-Policy: sandbox allow-forms;'], + ]; + } } From 67a8b30ba6dfe9a25be958ae0fc3f5cb1aeab231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bundyra?= Date: Mon, 2 Dec 2019 19:41:25 +0000 Subject: [PATCH 2/7] CSP header - group valid directive names --- src/Header/ContentSecurityPolicy.php | 31 +++++++++++++++++----------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/Header/ContentSecurityPolicy.php b/src/Header/ContentSecurityPolicy.php index 7b3470d0a0..1457c16649 100644 --- a/src/Header/ContentSecurityPolicy.php +++ b/src/Header/ContentSecurityPolicy.php @@ -21,31 +21,38 @@ class ContentSecurityPolicy implements MultipleHeaderInterface */ protected $validDirectiveNames = [ // As per http://www.w3.org/TR/CSP/#directives + // Fetch directives + 'child-src', + 'connect-src', 'default-src', - 'script-src', - 'object-src', - 'style-src', - 'img-src', - 'media-src', - 'frame-src', 'font-src', - 'connect-src', - 'sandbox', - 'report-uri', - 'child-src', + 'frame-src', + 'img-src', 'manifest-src', - 'worker-src', + 'media-src', + 'object-src', 'prefetch-src', + 'script-src', 'script-src-elem', 'script-src-attr', + 'style-src', 'style-src-elem', 'style-src-attr', + 'worker-src', + + // Document directives 'base-uri', 'plugin-types', + 'sandbox', + + // Navigation directives 'form-action', 'frame-ancestors', 'navigate-to', - 'report-to' + + // Reporting directives + 'report-uri', + 'report-to', ]; /** From 54ba0a9189e1615af63c2f62950b67a541fdbe9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bundyra?= Date: Mon, 2 Dec 2019 20:32:39 +0000 Subject: [PATCH 3/7] Change variable name in test --- test/Header/ContentSecurityPolicyTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Header/ContentSecurityPolicyTest.php b/test/Header/ContentSecurityPolicyTest.php index 430b3990e8..d9e77fd41a 100644 --- a/test/Header/ContentSecurityPolicyTest.php +++ b/test/Header/ContentSecurityPolicyTest.php @@ -192,16 +192,16 @@ public function testMultiple() * @dataProvider directivesProvider * * @param string $directive - * @param string[] $value + * @param string[] $values * @param string $expected */ public function testContentSecurityPolicySetDirectiveThrowsExceptionIfMissingDirectiveNameGiven( $directive, - array $value, + array $values, $expected ) { $csp = new ContentSecurityPolicy(); - $csp->setDirective($directive, $value); + $csp->setDirective($directive, $values); self::assertSame($expected, $csp->toString()); } From 6508f473fcd9285757e3a5624dc1e6c31c861666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bundyra?= Date: Mon, 2 Dec 2019 20:35:56 +0000 Subject: [PATCH 4/7] Rename data provider --- test/Header/ContentSecurityPolicyTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Header/ContentSecurityPolicyTest.php b/test/Header/ContentSecurityPolicyTest.php index d9e77fd41a..763c4c5dc7 100644 --- a/test/Header/ContentSecurityPolicyTest.php +++ b/test/Header/ContentSecurityPolicyTest.php @@ -189,7 +189,7 @@ public function testMultiple() } /** - * @dataProvider directivesProvider + * @dataProvider validDirectives * * @param string $directive * @param string[] $values @@ -206,7 +206,7 @@ public function testContentSecurityPolicySetDirectiveThrowsExceptionIfMissingDir self::assertSame($expected, $csp->toString()); } - public static function directivesProvider() + public static function validDirectives() { return [ ['child-src', ["'self'"],"Content-Security-Policy: child-src 'self';"], From 8155ce4992dc12f5ca41a8790bf0a5d7581dd7fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bundyra?= Date: Mon, 2 Dec 2019 20:36:11 +0000 Subject: [PATCH 5/7] Array formatting fix - each element in separate line --- test/Header/ContentSecurityPolicyTest.php | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/test/Header/ContentSecurityPolicyTest.php b/test/Header/ContentSecurityPolicyTest.php index 763c4c5dc7..c8a3da76c9 100644 --- a/test/Header/ContentSecurityPolicyTest.php +++ b/test/Header/ContentSecurityPolicyTest.php @@ -219,18 +219,14 @@ public static function validDirectives() ['style-src-attr', ["'self'"], "Content-Security-Policy: style-src-attr 'self';"], ['base-uri', ["'self'", "'unsafe-inline'"], "Content-Security-Policy: base-uri 'self' 'unsafe-inline';"], ['plugin-types', ['text/csv'], 'Content-Security-Policy: plugin-types text/csv;'], - ['form-action', - [ - 'http://*.example.com', - "'self'" - ], + [ + 'form-action', + ['http://*.example.com', "'self'"], "Content-Security-Policy: form-action http://*.example.com 'self';" ], - ['frame-ancestors', - [ - 'http://*.example.com', - "'self'" - ], + [ + 'frame-ancestors', + ['http://*.example.com', "'self'"], "Content-Security-Policy: frame-ancestors http://*.example.com 'self';" ], ['navigate-to', ['example.com'], 'Content-Security-Policy: navigate-to example.com;'], From 58688eec1e54c8b280236a3ef54ef93be1d35292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bundyra?= Date: Mon, 2 Dec 2019 20:37:13 +0000 Subject: [PATCH 6/7] Adds test to check valid directives also on parsing header from string --- test/Header/ContentSecurityPolicyTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/Header/ContentSecurityPolicyTest.php b/test/Header/ContentSecurityPolicyTest.php index c8a3da76c9..891b9dd555 100644 --- a/test/Header/ContentSecurityPolicyTest.php +++ b/test/Header/ContentSecurityPolicyTest.php @@ -233,4 +233,19 @@ public static function validDirectives() ['sandbox', ['allow-forms'], 'Content-Security-Policy: sandbox allow-forms;'], ]; } + + /** + * @dataProvider validDirectives + * + * @param string $directive + * @param string[] $values + * @param string $header + */ + public function testFromString($directive, array $values, $header) + { + $contentSecurityPolicy = ContentSecurityPolicy::fromString($header); + + self::assertArrayHasKey($directive, $contentSecurityPolicy->getDirectives()); + self::assertSame(implode(' ', $values), $contentSecurityPolicy->getDirectives()[$directive]); + } } From 0ec168ca9d992ef16839e28dd26e265c370ccd99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bundyra?= Date: Mon, 2 Dec 2019 20:38:38 +0000 Subject: [PATCH 7/7] Move test below data provider --- test/Header/ContentSecurityPolicyTest.php | 36 +++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/test/Header/ContentSecurityPolicyTest.php b/test/Header/ContentSecurityPolicyTest.php index 891b9dd555..fdcb068540 100644 --- a/test/Header/ContentSecurityPolicyTest.php +++ b/test/Header/ContentSecurityPolicyTest.php @@ -188,24 +188,6 @@ public function testMultiple() ); } - /** - * @dataProvider validDirectives - * - * @param string $directive - * @param string[] $values - * @param string $expected - */ - public function testContentSecurityPolicySetDirectiveThrowsExceptionIfMissingDirectiveNameGiven( - $directive, - array $values, - $expected - ) { - $csp = new ContentSecurityPolicy(); - $csp->setDirective($directive, $values); - - self::assertSame($expected, $csp->toString()); - } - public static function validDirectives() { return [ @@ -234,6 +216,24 @@ public static function validDirectives() ]; } + /** + * @dataProvider validDirectives + * + * @param string $directive + * @param string[] $values + * @param string $expected + */ + public function testContentSecurityPolicySetDirectiveThrowsExceptionIfMissingDirectiveNameGiven( + $directive, + array $values, + $expected + ) { + $csp = new ContentSecurityPolicy(); + $csp->setDirective($directive, $values); + + self::assertSame($expected, $csp->toString()); + } + /** * @dataProvider validDirectives *