Skip to content

Commit 23d9047

Browse files
authored
Merge pull request #5419 from kenjis/feat-secure-headers
feat: add SecureHeaders filter
2 parents 262cf0b + 32ca70c commit 23d9047

4 files changed

Lines changed: 133 additions & 5 deletions

File tree

app/Config/Filters.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use CodeIgniter\Filters\DebugToolbar;
88
use CodeIgniter\Filters\Honeypot;
99
use CodeIgniter\Filters\InvalidChars;
10+
use CodeIgniter\Filters\SecureHeaders;
1011

1112
class Filters extends BaseConfig
1213
{
@@ -17,10 +18,11 @@ class Filters extends BaseConfig
1718
* @var array
1819
*/
1920
public $aliases = [
20-
'csrf' => CSRF::class,
21-
'toolbar' => DebugToolbar::class,
22-
'honeypot' => Honeypot::class,
23-
'invalidchars' => InvalidChars::class,
21+
'csrf' => CSRF::class,
22+
'toolbar' => DebugToolbar::class,
23+
'honeypot' => Honeypot::class,
24+
'invalidchars' => InvalidChars::class,
25+
'secureheaders' => SecureHeaders::class,
2426
];
2527

2628
/**
@@ -38,6 +40,7 @@ class Filters extends BaseConfig
3840
'after' => [
3941
'toolbar',
4042
// 'honeypot',
43+
// 'secureheaders',
4144
],
4245
];
4346

system/Filters/SecureHeaders.php

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
/**
4+
* This file is part of CodeIgniter 4 framework.
5+
*
6+
* (c) CodeIgniter Foundation <admin@codeigniter.com>
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*/
11+
12+
namespace CodeIgniter\Filters;
13+
14+
use CodeIgniter\HTTP\RequestInterface;
15+
use CodeIgniter\HTTP\ResponseInterface;
16+
17+
/**
18+
* Add Common Security Headers
19+
*/
20+
class SecureHeaders implements FilterInterface
21+
{
22+
/**
23+
* @var array<string, string>
24+
*/
25+
protected $headers = [
26+
// https://owasp.org/www-project-secure-headers/#x-frame-options
27+
'X-Frame-Options' => 'SAMEORIGIN',
28+
29+
// https://owasp.org/www-project-secure-headers/#x-content-type-options
30+
'X-Content-Type-Options' => 'nosniff',
31+
32+
// https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/jj542450(v=vs.85)#the-noopen-directive
33+
'X-Download-Options' => 'noopen',
34+
35+
// https://owasp.org/www-project-secure-headers/#x-permitted-cross-domain-policies
36+
'X-Permitted-Cross-Domain-Policies' => 'none',
37+
38+
// https://owasp.org/www-project-secure-headers/#referrer-policy
39+
'Referrer-Policy' => 'same-origin',
40+
41+
// https://owasp.org/www-project-secure-headers/#x-xss-protection
42+
// If you do not need to support legacy browsers, it is recommended that you use
43+
// Content-Security-Policy without allowing unsafe-inline scripts instead.
44+
// 'X-XSS-Protection' => '1; mode=block',
45+
];
46+
47+
/**
48+
* We don't have anything to do here.
49+
*
50+
* @param array|null $arguments
51+
*
52+
* @return void
53+
*/
54+
public function before(RequestInterface $request, $arguments = null)
55+
{
56+
}
57+
58+
/**
59+
* Add security headers.
60+
*
61+
* @param array|null $arguments
62+
*
63+
* @return void
64+
*/
65+
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
66+
{
67+
foreach ($this->headers as $header => $value) {
68+
$response->setHeader($header, $value);
69+
}
70+
}
71+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/**
4+
* This file is part of CodeIgniter 4 framework.
5+
*
6+
* (c) CodeIgniter Foundation <admin@codeigniter.com>
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*/
11+
12+
namespace CodeIgniter\Filters;
13+
14+
use CodeIgniter\Config\Services;
15+
use CodeIgniter\Test\CIUnitTestCase;
16+
17+
/**
18+
* @internal
19+
*/
20+
final class SecureHeadersTest extends CIUnitTestCase
21+
{
22+
protected $request;
23+
protected $response;
24+
25+
public function testAfter()
26+
{
27+
$filter = new SecureHeaders();
28+
$request = Services::request(null, false);
29+
$response = Services::response(null, false);
30+
31+
$filter->after($request, $response);
32+
33+
$responseHeaders = $response->headers();
34+
$headers = $this->getPrivateProperty($filter, 'headers');
35+
36+
foreach ($headers as $header => $value) {
37+
$this->assertSame($value, $responseHeaders[$header]->getValue());
38+
}
39+
}
40+
}

user_guide_src/source/incoming/filters.rst

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,20 @@ In this example, the array ``['dual', 'noreturn']`` will be passed in ``$argumen
193193
Provided Filters
194194
****************
195195

196-
The filters bundled with CodeIgniter4 are: ``Honeypot``, ``CSRF``, ``DebugToolbar``, and ``InvalidChars``.
196+
The filters bundled with CodeIgniter4 are: ``Honeypot``, ``CSRF``, ``InvalidChars``, ``SecureHeaders``, and ``DebugToolbar``.
197197

198198
.. note:: The filters are executed in the order defined in the config file. However, if enabled, ``DebugToolbar`` is always executed last because it should be able to capture everything that happens in the other filters.
199+
200+
SecureHeaders
201+
=============
202+
203+
This filter adds HTTP response headers that your application can use to increase the security of your application.
204+
205+
If you want to customize the headers, extend ``CodeIgniter\Filters\SecureHeaders`` and override the ``$headers`` property. And change the ``$aliases`` property in **app/Config/Filters.php**::
206+
207+
public $aliases = [
208+
...
209+
'secureheaders' => \App\Filters\SecureHeaders::class,
210+
];
211+
212+
If you want to know about secure headers, see `OWASP Secure Headers Project <https://owasp.org/www-project-secure-headers/>`_.

0 commit comments

Comments
 (0)