Skip to content

Commit c966780

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

File tree

2 files changed

+79
-13
lines changed

2 files changed

+79
-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: 65 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;
@@ -50,4 +51,68 @@ public function testCreateShouldReturnPolicy(): void
5051

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

0 commit comments

Comments
 (0)