Skip to content

Commit 55c6ba7

Browse files
committed
BUGFIX: valid custom directive is not added to csp header
1 parent ec3e054 commit 55c6ba7

File tree

2 files changed

+80
-13
lines changed

2 files changed

+80
-13
lines changed

Classes/Factory/PolicyFactory.php

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,28 @@
1515
class PolicyFactory
1616
{
1717
/**
18-
* @param string[][] $defaultDirective
19-
* @param string[][] $customDirective
18+
* @param string[][] $defaultDirectives
19+
* @param string[][] $customDirectives
2020
* @throws InvalidDirectiveException
2121
*/
22-
public function create(Nonce $nonce, array $defaultDirective, array $customDirective): Policy
22+
public function create(Nonce $nonce, array $defaultDirectives, array $customDirectives): Policy
2323
{
24-
$directiveCollections = [$defaultDirective, $customDirective];
25-
$defaultDirective = array_shift($directiveCollections);
26-
27-
array_walk($defaultDirective, function (array &$item, string $key) use ($directiveCollections) {
28-
foreach ($directiveCollections as $collection) {
29-
if (array_key_exists($key, $collection)) {
30-
$item = array_unique([...$item, ...$collection[$key]]);
31-
}
24+
$resultDirectives = $defaultDirectives;
25+
foreach ($customDirectives as $key => $customDirective) {
26+
if (array_key_exists($key, $resultDirectives)) {
27+
$resultDirectives[$key] = array_merge($resultDirectives[$key], $customDirective);
28+
} else {
29+
// Custom directive is not present in default, still needs to be added.
30+
$resultDirectives[$key] = $customDirective;
3231
}
33-
});
32+
33+
$resultDirectives[$key] = array_unique($resultDirectives[$key]);
34+
}
3435

3536
$policy = new Policy();
3637
$policy->setNonce($nonce);
3738

38-
foreach ($defaultDirective as $directive => $values) {
39+
foreach ($resultDirectives as $directive => $values) {
3940
$policy->addDirective($directive, $values);
4041
}
4142

Tests/Unit/Factory/PolicyFactoryTest.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Unit\Factory;
66

7+
use Flowpack\ContentSecurityPolicy\Exceptions\InvalidDirectiveException;
78
use Flowpack\ContentSecurityPolicy\Factory\PolicyFactory;
89
use Flowpack\ContentSecurityPolicy\Model\Directive;
910
use Flowpack\ContentSecurityPolicy\Model\Nonce;
@@ -15,6 +16,7 @@
1516
#[CoversClass(PolicyFactory::class)]
1617
#[UsesClass(Policy::class)]
1718
#[UsesClass(Directive::class)]
19+
#[UsesClass(InvalidDirectiveException::class)]
1820
class PolicyFactoryTest extends TestCase
1921
{
2022
public function testCreateShouldReturnPolicy(): void
@@ -50,4 +52,68 @@ public function testCreateShouldReturnPolicy(): void
5052

5153
self::assertSame($expected, $result->getDirectives());
5254
}
55+
56+
public function testCreateShouldFailWithInvalidDirective(): void
57+
{
58+
$policyFactory = new PolicyFactory();
59+
$nonceMock = $this->createMock(Nonce::class);
60+
61+
$defaultDirective = [
62+
'base-uri' => [
63+
'self',
64+
],
65+
'script-src' => [
66+
'self',
67+
],
68+
];
69+
$customDirective = [
70+
'invalid' => [
71+
'{nonce}',
72+
],
73+
];
74+
75+
$this->expectException(InvalidDirectiveException::class);
76+
$policyFactory->create($nonceMock, $defaultDirective, $customDirective);
77+
}
78+
79+
public function testCreateShouldAddDirectiveWhichIsPresentInCustomButNotDefaultConfiguration(): void
80+
{
81+
$policyFactory = new PolicyFactory();
82+
$nonceMock = $this->createMock(Nonce::class);
83+
84+
$defaultDirective = [
85+
'base-uri' => [
86+
'self',
87+
],
88+
'script-src' => [
89+
'self',
90+
],
91+
];
92+
$customDirective = [
93+
'script-src' => [
94+
'{nonce}',
95+
],
96+
'worker-src' => [
97+
'self',
98+
'self',
99+
],
100+
];
101+
102+
$expected = [
103+
'base-uri' => [
104+
"'self'",
105+
],
106+
'script-src' => [
107+
"'self'",
108+
"'nonce-'",
109+
],
110+
'worker-src' => [
111+
"'self'",
112+
],
113+
];
114+
115+
$result = $policyFactory->create($nonceMock, $defaultDirective, $customDirective);
116+
117+
self::assertSame($expected, $result->getDirectives());
118+
}
53119
}

0 commit comments

Comments
 (0)