Skip to content

Commit 3846204

Browse files
authored
Merge pull request #8220 from kenjis/feat-csp-clearDirective
feat: add CSP clearDirective() to clear existing directive
2 parents bf7725c + 3ac6433 commit 3846204

File tree

5 files changed

+94
-30
lines changed

5 files changed

+94
-30
lines changed

system/HTTP/ContentSecurityPolicy.php

+49-28
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,31 @@
2626
*/
2727
class ContentSecurityPolicy
2828
{
29+
/**
30+
* CSP directives
31+
*
32+
* @var array<string, string>
33+
*/
34+
protected array $directives = [
35+
'base-uri' => 'baseURI',
36+
'child-src' => 'childSrc',
37+
'connect-src' => 'connectSrc',
38+
'default-src' => 'defaultSrc',
39+
'font-src' => 'fontSrc',
40+
'form-action' => 'formAction',
41+
'frame-ancestors' => 'frameAncestors',
42+
'frame-src' => 'frameSrc',
43+
'img-src' => 'imageSrc',
44+
'media-src' => 'mediaSrc',
45+
'object-src' => 'objectSrc',
46+
'plugin-types' => 'pluginTypes',
47+
'script-src' => 'scriptSrc',
48+
'style-src' => 'styleSrc',
49+
'manifest-src' => 'manifestSrc',
50+
'sandbox' => 'sandbox',
51+
'report-uri' => 'reportURI',
52+
];
53+
2954
/**
3055
* Used for security enforcement
3156
*
@@ -113,37 +138,37 @@ class ContentSecurityPolicy
113138
/**
114139
* Used for security enforcement
115140
*
116-
* @var string
141+
* @var array|string
117142
*/
118-
protected $reportURI;
143+
protected $scriptSrc = [];
119144

120145
/**
121146
* Used for security enforcement
122147
*
123148
* @var array|string
124149
*/
125-
protected $sandbox = [];
150+
protected $styleSrc = [];
126151

127152
/**
128153
* Used for security enforcement
129154
*
130155
* @var array|string
131156
*/
132-
protected $scriptSrc = [];
157+
protected $manifestSrc = [];
133158

134159
/**
135160
* Used for security enforcement
136161
*
137162
* @var array|string
138163
*/
139-
protected $styleSrc = [];
164+
protected $sandbox = [];
140165

141166
/**
142167
* Used for security enforcement
143168
*
144-
* @var array|string
169+
* @var string|null
145170
*/
146-
protected $manifestSrc = [];
171+
protected $reportURI;
147172

148173
/**
149174
* Used for security enforcement
@@ -704,26 +729,6 @@ protected function buildHeaders(ResponseInterface $response)
704729
$response->setHeader('Content-Security-Policy', []);
705730
$response->setHeader('Content-Security-Policy-Report-Only', []);
706731

707-
$directives = [
708-
'base-uri' => 'baseURI',
709-
'child-src' => 'childSrc',
710-
'connect-src' => 'connectSrc',
711-
'default-src' => 'defaultSrc',
712-
'font-src' => 'fontSrc',
713-
'form-action' => 'formAction',
714-
'frame-ancestors' => 'frameAncestors',
715-
'frame-src' => 'frameSrc',
716-
'img-src' => 'imageSrc',
717-
'media-src' => 'mediaSrc',
718-
'object-src' => 'objectSrc',
719-
'plugin-types' => 'pluginTypes',
720-
'script-src' => 'scriptSrc',
721-
'style-src' => 'styleSrc',
722-
'manifest-src' => 'manifestSrc',
723-
'sandbox' => 'sandbox',
724-
'report-uri' => 'reportURI',
725-
];
726-
727732
// inject default base & default URIs if needed
728733
if (empty($this->baseURI)) {
729734
$this->baseURI = 'self';
@@ -733,7 +738,7 @@ protected function buildHeaders(ResponseInterface $response)
733738
$this->defaultSrc = 'self';
734739
}
735740

736-
foreach ($directives as $name => $property) {
741+
foreach ($this->directives as $name => $property) {
737742
if (! empty($this->{$property})) {
738743
$this->addToHeader($name, $this->{$property});
739744
}
@@ -814,4 +819,20 @@ protected function addToHeader(string $name, $values = null)
814819
$this->reportOnlyHeaders[$name] = implode(' ', $reportSources);
815820
}
816821
}
822+
823+
/**
824+
* Clear the directive.
825+
*
826+
* @param string $directive CSP directive
827+
*/
828+
public function clearDirective(string $directive): void
829+
{
830+
if ($directive === 'report-uris') {
831+
$this->{$this->directives[$directive]} = null;
832+
833+
return;
834+
}
835+
836+
$this->{$this->directives[$directive]} = [];
837+
}
817838
}

tests/system/HTTP/ContentSecurityPolicyTest.php

+18
Original file line numberDiff line numberDiff line change
@@ -642,4 +642,22 @@ public function testHeaderScriptNonceEmittedOnceGetScriptNonceCalled(): void
642642
$result = $this->getHeaderEmitted('Content-Security-Policy');
643643
$this->assertStringContainsString("script-src 'self' 'nonce-", $result);
644644
}
645+
646+
public function testClearDirective(): void
647+
{
648+
$this->prepare();
649+
650+
$this->csp->addStyleSrc('css.example.com');
651+
$this->csp->clearDirective('style-src');
652+
653+
$this->csp->setReportURI('http://example.com/csp/reports');
654+
$this->csp->clearDirective('report-uri');
655+
$this->csp->finalize($this->response);
656+
657+
$header = $this->response->getHeaderLine('Content-Security-Policy');
658+
659+
$this->assertStringNotContainsString('style-src ', $header);
660+
$this->assertStringNotContainsString('css.example.com', $header);
661+
$this->assertStringNotContainsString('report-uri', $header);
662+
}
645663
}

user_guide_src/source/changelogs/v4.5.0.rst

+2
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ Others
240240
- ``FileLocatorInterface`` has been added.
241241
- **CodeIgniter:** Added a pseudo-variable ``{memory_usage}`` to show your memory
242242
usage in your view files, which was supported by CodeIgniter 3.
243+
- **CSP:** Added ``ContentSecurityPolicy::clearDirective()`` method to clear
244+
existing CSP directives. See :ref:`csp-clear-directives`.
243245

244246
Message Changes
245247
***************

user_guide_src/source/outgoing/csp.rst

+19-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ call basis, by providing an optional second parameter to the adding method call.
6666
Runtime Configuration
6767
*********************
6868

69-
If your application needs to make changes at run-time, you can access the instance at ``$this->response->getCSP()`` in your controllers. The
69+
If your application needs to make changes at run-time, you can access the instance at ``$this->response->getCSP()`` in your controllers.
70+
71+
The
7072
class holds a number of methods that map pretty clearly to the appropriate header value that you need to set.
7173
Examples are shown below, with different combinations of parameters, though all accept either a directive
7274
name or an array of them:
@@ -76,12 +78,27 @@ name or an array of them:
7678
The first parameter to each of the "add" methods is an appropriate string value,
7779
or an array of them.
7880

81+
Report Only
82+
===========
83+
7984
The ``reportOnly()`` method allows you to specify the default reporting treatment
80-
for subsequent sources, unless over-ridden. For instance, you could specify
85+
for subsequent sources, unless over-ridden.
86+
87+
For instance, you could specify
8188
that youtube.com was allowed, and then provide several allowed but reported sources:
8289

8390
.. literalinclude:: csp/013.php
8491

92+
.. _csp-clear-directives:
93+
94+
Clear Directives
95+
================
96+
97+
If you want to clear existing CSP directives, you can use the ``clearDirective()``
98+
method:
99+
100+
.. literalinclude:: csp/014.php
101+
85102
**************
86103
Inline Content
87104
**************
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
3+
// get the CSP instance
4+
$csp = $this->response->getCSP();
5+
6+
$csp->clearDirective('style-src');

0 commit comments

Comments
 (0)