diff --git a/system/HTTP/ContentSecurityPolicy.php b/system/HTTP/ContentSecurityPolicy.php index b674383e5470..92597d259d2b 100644 --- a/system/HTTP/ContentSecurityPolicy.php +++ b/system/HTTP/ContentSecurityPolicy.php @@ -402,6 +402,22 @@ public function enabled(): bool return $this->CSPEnabled; } + /** + * Enable Content Security Policy enforcement. + */ + public function enable(): void + { + $this->CSPEnabled = true; + } + + /** + * Disable Content Security Policy enforcement. + */ + public function disable(): void + { + $this->CSPEnabled = false; + } + /** * Whether adding nonce in style-* directives is enabled or not. */ diff --git a/tests/system/HTTP/ContentSecurityPolicyTest.php b/tests/system/HTTP/ContentSecurityPolicyTest.php index de9670fdf749..2ff7871caddb 100644 --- a/tests/system/HTTP/ContentSecurityPolicyTest.php +++ b/tests/system/HTTP/ContentSecurityPolicyTest.php @@ -91,6 +91,26 @@ public function testExistence(): void $this->assertHeaderEmitted('Content-Security-Policy:'); } + #[PreserveGlobalState(false)] + #[RunInSeparateProcess] + public function testDisable(): void + { + $this->prepare(true); + $this->csp->disable(); + $this->assertTrue($this->work()); + $this->assertHeaderNotEmitted('Content-Security-Policy:'); + } + + #[PreserveGlobalState(false)] + #[RunInSeparateProcess] + public function testEnable(): void + { + $this->prepare(false); + $this->csp->enable(); + $this->assertTrue($this->work()); + $this->assertHeaderEmitted('Content-Security-Policy:'); + } + #[PreserveGlobalState(false)] #[RunInSeparateProcess] public function testReportOnly(): void diff --git a/user_guide_src/source/changelogs/v4.8.0.rst b/user_guide_src/source/changelogs/v4.8.0.rst index 04c221b54396..6ce487af09e7 100644 --- a/user_guide_src/source/changelogs/v4.8.0.rst +++ b/user_guide_src/source/changelogs/v4.8.0.rst @@ -321,6 +321,7 @@ HTTP For example: ``php index.php command -- --myarg`` will pass ``--myarg`` as an argument instead of an option. - ``CLIRequest`` now supports options with values specified using an equals sign (e.g., ``--option=value``) in addition to the existing space-separated syntax (e.g., ``--option value``). This provides more flexibility in how you can pass options to CLI requests. +- Added ``enable()`` and ``disable()`` methods to ``ContentSecurityPolicy`` to enable or disable the CSP header for the current request. See :ref:`csp-enable-disable`. - Added ``$enableStyleNonce`` and ``$enableScriptNonce`` options to ``Config\App`` to automatically add nonces to control whether to add nonces to style-* and script-* directives in the Content Security Policy (CSP) header when CSP is enabled. See :ref:`csp-control-nonce-generation` for details. - Added ``URI::withQuery()``, ``URI::withQueryArray()``, ``URI::withoutQueryVars()``, and ``URI::withOnlyQueryVars()`` to return cloned URIs with replaced or filtered query variables. - Added ``URI::withQueryVar()`` and ``URI::withQueryVars()`` to return a cloned URI with query variables added or replaced. diff --git a/user_guide_src/source/outgoing/csp.rst b/user_guide_src/source/outgoing/csp.rst index f6abc8793aa6..ae8c145c4b71 100644 --- a/user_guide_src/source/outgoing/csp.rst +++ b/user_guide_src/source/outgoing/csp.rst @@ -78,6 +78,30 @@ name or an array of them: The first parameter to each of the "add" methods is an appropriate string value, or an array of them. +.. _csp-enable-disable: + +Enable or Disable CSP at Runtime +================================ + +.. versionadded:: 4.8.0 + +You can enable or disable CSP for the current request by using the +``enable()`` and ``disable()`` methods on the CSP instance. + +For example, to enable/disable CSP for a specific response: + +.. literalinclude:: csp/017.php + +The runtime value takes precedence over the ``CSPEnabled`` configuration value +for the current response. + +These methods only affect the current response. After the response has been sent, +the CSP instance is recreated and the value of ``CSPEnabled`` in +**app/Config/App.php** is used as the default for subsequent requests. + +This allows applications to keep CSP enabled globally while temporarily disabling +it for specific responses, or enable it only where required. + Report Only =========== diff --git a/user_guide_src/source/outgoing/csp/017.php b/user_guide_src/source/outgoing/csp/017.php new file mode 100644 index 000000000000..71620b6e9a87 --- /dev/null +++ b/user_guide_src/source/outgoing/csp/017.php @@ -0,0 +1,10 @@ +response->getCSP(); + +// Disable CSP for the request +$csp->disable(); + +// Re-enable CSP for the request +$csp->enable();