Skip to content

Commit 9521798

Browse files
committed
feat: Add CSP registry for unsafe inline scripts
This provides a registry for registering unsafe inline scripts. Their hashes will be added to the "script-src" part of the Content-Security-Policy header.
1 parent a862ed4 commit 9521798

4 files changed

Lines changed: 68 additions & 4 deletions

File tree

Classes/Http/Middleware/ContentSecurityPolicyMiddleware.php renamed to Classes/ContentSecurityPolicy/ContentSecurityPolicyMiddleware.php

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace Netlogix\Sentry\Http\Middleware;
5+
namespace Netlogix\Sentry\ContentSecurityPolicy;
66

77
use GuzzleHttp\Psr7\Uri;
88
use Neos\Flow\Annotations as Flow;
@@ -26,6 +26,9 @@ class ContentSecurityPolicyMiddleware implements MiddlewareInterface
2626
#[Flow\InjectConfiguration(path: 'csp.headers.parts')]
2727
protected array $parts = [];
2828

29+
#[Flow\Inject]
30+
protected Registry $registry;
31+
2932
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
3033
{
3134
$response = $handler->handle($request);
@@ -53,13 +56,27 @@ protected function addContentSecurityPolicy(
5356
$headerName = 'Content-Security-Policy';
5457
}
5558

59+
$parts = $this->parts;
60+
if ($this->registry->getSafeInlineScriptHashes() !== []) {
61+
$safeInlineScripts = join(
62+
' ',
63+
array_map(fn (string $hash) => sprintf("'%s'", $hash), $this->registry->getSafeInlineScriptHashes())
64+
);
65+
$existingScriptSrc = array_find_key($parts, fn (string $part) => str_starts_with($part, 'script-src'));
66+
67+
if ($existingScriptSrc !== null) {
68+
$parts[$existingScriptSrc] = $parts[$existingScriptSrc] . ' ' . $safeInlineScripts;
69+
} else {
70+
$parts[] = 'script-src ' . $safeInlineScripts;
71+
}
72+
}
73+
5674
$defaultParts = [
5775
'report-uri ' . $this->reportingEndpoint($request),
5876
'report-to csp-endpoint'
5977
];
6078

61-
// TODO: Add support for nonces
62-
$parts = array_merge($this->parts, $defaultParts);
79+
$parts = array_merge($parts, $defaultParts);
6380

6481
return $response
6582
->withHeader($headerName, trim(join('; ', $parts), "; \n\r\t\v\0"));
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Netlogix\Sentry\ContentSecurityPolicy;
6+
7+
use Neos\Eel\ProtectedContextAwareInterface;
8+
use Neos\Flow\Annotations as Flow;
9+
10+
/**
11+
* @Flow\Scope("singleton")
12+
*/
13+
#[Flow\Scope('singleton')]
14+
class Registry implements ProtectedContextAwareInterface
15+
{
16+
protected static array $safeInlineScriptHashes = [];
17+
18+
/**
19+
* Registers a safe inline script from the provided source.
20+
*
21+
* @param string $script The script content that needs to be registered as a safe inline script.
22+
* @param string $algorithm The algorithm to use for hashing the script content (default: sha256)
23+
* @return string The trimmed script content is returned
24+
*/
25+
public function registerSafeInlineScriptFromSource(string $script, string $algorithm = 'sha256'): string
26+
{
27+
$hash = base64_encode(hash($algorithm, $script, true));
28+
self::$safeInlineScriptHashes[] = sprintf('%s-%s', $algorithm, $hash);
29+
30+
return $script;
31+
}
32+
33+
public function getSafeInlineScriptHashes(): array
34+
{
35+
return self::$safeInlineScriptHashes;
36+
}
37+
38+
public function allowsCallOfMethod($methodName): bool
39+
{
40+
return true;
41+
}
42+
}

Configuration/Settings.Eel.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Neos:
2+
# Fusion might not be installed, but adding the Registry to the defaultContext won't hurt
3+
Fusion:
4+
defaultContext:
5+
'Netlogix.CspRegistry': 'Netlogix\Sentry\ContentSecurityPolicy\Registry'

Configuration/Settings.Middleware.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ Neos:
44
middlewares:
55
'nlxSentryContentSecurityPolicy':
66
position: 'before dispatch'
7-
middleware: 'Netlogix\Sentry\Http\Middleware\ContentSecurityPolicyMiddleware'
7+
middleware: 'Netlogix\Sentry\ContentSecurityPolicy\ContentSecurityPolicyMiddleware'

0 commit comments

Comments
 (0)