Skip to content

Commit

Permalink
Merge pull request #5419 from kenjis/feat-secure-headers
Browse files Browse the repository at this point in the history
feat: add SecureHeaders filter
  • Loading branch information
kenjis authored Dec 8, 2021
2 parents 262cf0b + 32ca70c commit 23d9047
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 5 deletions.
11 changes: 7 additions & 4 deletions app/Config/Filters.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use CodeIgniter\Filters\DebugToolbar;
use CodeIgniter\Filters\Honeypot;
use CodeIgniter\Filters\InvalidChars;
use CodeIgniter\Filters\SecureHeaders;

class Filters extends BaseConfig
{
Expand All @@ -17,10 +18,11 @@ class Filters extends BaseConfig
* @var array
*/
public $aliases = [
'csrf' => CSRF::class,
'toolbar' => DebugToolbar::class,
'honeypot' => Honeypot::class,
'invalidchars' => InvalidChars::class,
'csrf' => CSRF::class,
'toolbar' => DebugToolbar::class,
'honeypot' => Honeypot::class,
'invalidchars' => InvalidChars::class,
'secureheaders' => SecureHeaders::class,
];

/**
Expand All @@ -38,6 +40,7 @@ class Filters extends BaseConfig
'after' => [
'toolbar',
// 'honeypot',
// 'secureheaders',
],
];

Expand Down
71 changes: 71 additions & 0 deletions system/Filters/SecureHeaders.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace CodeIgniter\Filters;

use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;

/**
* Add Common Security Headers
*/
class SecureHeaders implements FilterInterface
{
/**
* @var array<string, string>
*/
protected $headers = [
// https://owasp.org/www-project-secure-headers/#x-frame-options
'X-Frame-Options' => 'SAMEORIGIN',

// https://owasp.org/www-project-secure-headers/#x-content-type-options
'X-Content-Type-Options' => 'nosniff',

// https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/jj542450(v=vs.85)#the-noopen-directive
'X-Download-Options' => 'noopen',

// https://owasp.org/www-project-secure-headers/#x-permitted-cross-domain-policies
'X-Permitted-Cross-Domain-Policies' => 'none',

// https://owasp.org/www-project-secure-headers/#referrer-policy
'Referrer-Policy' => 'same-origin',

// https://owasp.org/www-project-secure-headers/#x-xss-protection
// If you do not need to support legacy browsers, it is recommended that you use
// Content-Security-Policy without allowing unsafe-inline scripts instead.
// 'X-XSS-Protection' => '1; mode=block',
];

/**
* We don't have anything to do here.
*
* @param array|null $arguments
*
* @return void
*/
public function before(RequestInterface $request, $arguments = null)
{
}

/**
* Add security headers.
*
* @param array|null $arguments
*
* @return void
*/
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
foreach ($this->headers as $header => $value) {
$response->setHeader($header, $value);
}
}
}
40 changes: 40 additions & 0 deletions tests/system/Filters/SecureHeadersTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace CodeIgniter\Filters;

use CodeIgniter\Config\Services;
use CodeIgniter\Test\CIUnitTestCase;

/**
* @internal
*/
final class SecureHeadersTest extends CIUnitTestCase
{
protected $request;
protected $response;

public function testAfter()
{
$filter = new SecureHeaders();
$request = Services::request(null, false);
$response = Services::response(null, false);

$filter->after($request, $response);

$responseHeaders = $response->headers();
$headers = $this->getPrivateProperty($filter, 'headers');

foreach ($headers as $header => $value) {
$this->assertSame($value, $responseHeaders[$header]->getValue());
}
}
}
16 changes: 15 additions & 1 deletion user_guide_src/source/incoming/filters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,20 @@ In this example, the array ``['dual', 'noreturn']`` will be passed in ``$argumen
Provided Filters
****************

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

.. 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.

SecureHeaders
=============

This filter adds HTTP response headers that your application can use to increase the security of your application.

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**::

public $aliases = [
...
'secureheaders' => \App\Filters\SecureHeaders::class,
];

If you want to know about secure headers, see `OWASP Secure Headers Project <https://owasp.org/www-project-secure-headers/>`_.

0 comments on commit 23d9047

Please sign in to comment.