From 5f6b810dd4a75ad501c490ba5d3f8f0f74fb5f9b Mon Sep 17 00:00:00 2001 From: Bogdan Date: Tue, 13 Oct 2026 20:55:25 +0200 Subject: [PATCH] fix: make setDefaultSrc() add directives instead of overwriting --- system/HTTP/ContentSecurityPolicy.php | 21 +++++++++++-- .../system/HTTP/ContentSecurityPolicyTest.php | 30 +++++++++++++++++++ user_guide_src/source/changelogs/v4.7.6.rst | 1 + 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/system/HTTP/ContentSecurityPolicy.php b/system/HTTP/ContentSecurityPolicy.php index dfea52a62772..25532d742805 100644 --- a/system/HTTP/ContentSecurityPolicy.php +++ b/system/HTTP/ContentSecurityPolicy.php @@ -524,13 +524,30 @@ public function addConnectSrc($uri, ?bool $explicitReporting = null) * * @return $this */ - public function setDefaultSrc($uri, ?bool $explicitReporting = null) + public function addDefaultSrc($uri, ?bool $explicitReporting = null) { - $this->defaultSrc = [(string) $uri => $explicitReporting ?? $this->reportOnly]; + $this->addOption($uri, 'defaultSrc', $explicitReporting ?? $this->reportOnly); return $this; } + /** + * Adds a new value to the `default-src` directive. + * + * `default-src` is the URI that is used for many of the settings when + * no other source has been set. + * + * @see http://www.w3.org/TR/CSP/#directive-default-src + * + * @param list|string $uri + * + * @return $this + */ + public function setDefaultSrc($uri, ?bool $explicitReporting = null) + { + return $this->addDefaultSrc($uri, $explicitReporting); + } + /** * Adds a new value to the `font-src` directive. * diff --git a/tests/system/HTTP/ContentSecurityPolicyTest.php b/tests/system/HTTP/ContentSecurityPolicyTest.php index 780cb99f31ea..0e21170fb2d6 100644 --- a/tests/system/HTTP/ContentSecurityPolicyTest.php +++ b/tests/system/HTTP/ContentSecurityPolicyTest.php @@ -614,7 +614,37 @@ public function testDefaultSrc(): void $header = $this->getHeaderEmitted('Content-Security-Policy'); $this->assertIsString($header); + $this->assertContains('default-src maybe.com iffy.com', $this->getCspDirectives($header)); + } + + #[PreserveGlobalState(false)] + #[RunInSeparateProcess] + public function testDefaultSrcRich(): void + { + $this->csp->reportOnly(false); + $this->csp->setDefaultSrc(['self', 'maybe.com', 'iffy.com']); + $this->assertTrue($this->work()); + + $header = $this->getHeaderEmitted('Content-Security-Policy'); + $this->assertIsString($header); + $this->assertContains("default-src 'self' maybe.com iffy.com", $this->getCspDirectives($header)); + } + + #[PreserveGlobalState(false)] + #[RunInSeparateProcess] + public function testAddDefaultSrc(): void + { + $this->csp->addDefaultSrc('maybe.com'); + $this->csp->addDefaultSrc('iffy.com', true); + $this->assertTrue($this->work()); + + $header = $this->getHeaderEmitted('Content-Security-Policy-Report-Only'); + $this->assertIsString($header); $this->assertContains('default-src iffy.com', $this->getCspDirectives($header)); + + $header = $this->getHeaderEmitted('Content-Security-Policy'); + $this->assertIsString($header); + $this->assertContains('default-src maybe.com', $this->getCspDirectives($header)); } #[PreserveGlobalState(false)] diff --git a/user_guide_src/source/changelogs/v4.7.6.rst b/user_guide_src/source/changelogs/v4.7.6.rst index 360221806c4f..d169f8ebd267 100644 --- a/user_guide_src/source/changelogs/v4.7.6.rst +++ b/user_guide_src/source/changelogs/v4.7.6.rst @@ -31,6 +31,7 @@ Bugs Fixed ********** - **Commands:** Fixed a bug where generator commands did not sort the imports of a template with CRLF line endings. +- **HTTP:** Fixed a bug in ``ContentSecurityPolicy::setDefaultSrc()`` where it overwrote existing directives instead of adding them, and failed when passed an array of URIs. Added ``ContentSecurityPolicy::addDefaultSrc()`` for consistency with other directive methods. - **Security:** Fixed a bug where a valid JSON request body that is not an object (for example a JSON array) was corrupted after CSRF verification when the token was sent via the ``X-CSRF-TOKEN`` header.