Skip to content

Commit 2caca5b

Browse files
committed
Add granular nonces
1 parent f474a88 commit 2caca5b

File tree

3 files changed

+92
-6
lines changed

3 files changed

+92
-6
lines changed

app/Config/ContentSecurityPolicy.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,16 @@ class ContentSecurityPolicy extends BaseConfig
199199
*/
200200
public $sandbox;
201201

202+
/**
203+
* Enable nonce to style tags?
204+
*/
205+
public bool $enableStyleNonce = true;
206+
207+
/**
208+
* Enable nonce to script tags?
209+
*/
210+
public bool $enableScriptNonce = true;
211+
202212
/**
203213
* Nonce placeholder for style tags.
204214
*/

system/HTTP/ContentSecurityPolicy.php

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,20 @@ class ContentSecurityPolicy
298298
*/
299299
protected $scriptNonce;
300300

301+
/**
302+
* Whether to enable nonce to style-src and style-src-elem directives or not.
303+
*
304+
* @var bool
305+
*/
306+
protected $enableStyleNonce = true;
307+
308+
/**
309+
* Whether to enable nonce to script-src and script-src-elem directives or not.
310+
*
311+
* @var bool
312+
*/
313+
protected $enableScriptNonce = true;
314+
301315
/**
302316
* Nonce placeholder for style tags.
303317
*
@@ -399,10 +413,13 @@ public function getStyleNonce(): string
399413
{
400414
if ($this->styleNonce === null) {
401415
$this->styleNonce = base64_encode(random_bytes(12));
402-
$this->addStyleSrc('nonce-' . $this->styleNonce);
403416

404-
if ($this->styleSrcElem !== []) {
405-
$this->addStyleSrcElem('nonce-' . $this->styleNonce);
417+
if ($this->enableStyleNonce) {
418+
$this->addStyleSrc('nonce-' . $this->styleNonce);
419+
420+
if ($this->styleSrcElem !== []) {
421+
$this->addStyleSrcElem('nonce-' . $this->styleNonce);
422+
}
406423
}
407424
}
408425

@@ -416,10 +433,13 @@ public function getScriptNonce(): string
416433
{
417434
if ($this->scriptNonce === null) {
418435
$this->scriptNonce = base64_encode(random_bytes(12));
419-
$this->addScriptSrc('nonce-' . $this->scriptNonce);
420436

421-
if ($this->scriptSrcElem !== []) {
422-
$this->addScriptSrcElem('nonce-' . $this->scriptNonce);
437+
if ($this->enableScriptNonce) {
438+
$this->addScriptSrc('nonce-' . $this->scriptNonce);
439+
440+
if ($this->scriptSrcElem !== []) {
441+
$this->addScriptSrcElem('nonce-' . $this->scriptNonce);
442+
}
423443
}
424444
}
425445

@@ -868,6 +888,30 @@ public function addReportingEndpoints(array $endpoint): static
868888
return $this;
869889
}
870890

891+
/**
892+
* Enables or disables adding nonces to style-src and style-src-elem directives.
893+
*
894+
* @return $this
895+
*/
896+
public function setEnableStyleNonce(bool $value = true): static
897+
{
898+
$this->enableStyleNonce = $value;
899+
900+
return $this;
901+
}
902+
903+
/**
904+
* Enables or disables adding nonces to script-src and script-src-elem directives.
905+
*
906+
* @return $this
907+
*/
908+
public function setEnableScriptNonce(bool $value = true): static
909+
{
910+
$this->enableScriptNonce = $value;
911+
912+
return $this;
913+
}
914+
871915
/**
872916
* DRY method to add an string or array to a class property.
873917
*

tests/system/HTTP/ContentSecurityPolicyTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,22 @@ public function testBodyScriptNonce(): void
731731
$this->assertStringContainsString('nonce-', $header);
732732
}
733733

734+
public function testDisabledScriptNonce(): void
735+
{
736+
$this->csp->clearDirective('script-src');
737+
738+
$this->csp->setEnableScriptNonce(false);
739+
$this->csp->addScriptSrc('self');
740+
$this->csp->addScriptSrc('cdn.cloudy.com');
741+
742+
$this->assertTrue($this->work());
743+
744+
$header = $this->response->getHeaderLine('Content-Security-Policy');
745+
746+
$this->assertStringContainsString("script-src 'self' cdn.cloudy.com", $header);
747+
$this->assertStringNotContainsString("script-src 'self' cdn.cloudy.com nonce-", $header);
748+
}
749+
734750
public function testBodyScriptNonceCustomScriptTag(): void
735751
{
736752
$config = new CSPConfig();
@@ -810,6 +826,22 @@ public function testBodyStyleNonce(): void
810826
$this->assertStringContainsString('nonce-', $header);
811827
}
812828

829+
public function testDisabledStyleNonce(): void
830+
{
831+
$this->csp->clearDirective('style-src');
832+
833+
$this->csp->setEnableStyleNonce(false);
834+
$this->csp->addStyleSrc('self');
835+
$this->csp->addStyleSrc('cdn.cloudy.com');
836+
837+
$this->assertTrue($this->work());
838+
839+
$header = $this->response->getHeaderLine('Content-Security-Policy');
840+
841+
$this->assertStringContainsString("style-src 'self' cdn.cloudy.com", $header);
842+
$this->assertStringNotContainsString("style-src 'self' cdn.cloudy.com nonce-", $header);
843+
}
844+
813845
public function testBodyStyleNonceCustomStyleTag(): void
814846
{
815847
$config = new CSPConfig();

0 commit comments

Comments
 (0)