diff --git a/.symfony.bundle.yaml b/.symfony.bundle.yaml
new file mode 100644
index 0000000..1dc8b47
--- /dev/null
+++ b/.symfony.bundle.yaml
@@ -0,0 +1,8 @@
+branches:
+ - master
+maintained_branches:
+ - master
+current_branch: master
+dev_branch: master
+doc_dir: src/Resources/doc/
+dev_branch_alias: 3.x
diff --git a/README.md b/README.md
index d535d76..1f2d0af 100644
--- a/README.md
+++ b/README.md
@@ -6,830 +6,58 @@ The NelmioSecurityBundle provides additional security features for your Symfony
## Installation
-Require the `nelmio/security-bundle` package in your composer.json and update your dependencies.
+Require the `nelmio/security-bundle` package in your composer.json and update your dependencies:
$ composer require nelmio/security-bundle
-The bundle should be automatically enabled by Flex. In case you don't use Flex, you'll need to manually enable the
-bundle by adding the following line in the config/bundles.php file of your project:
-```php
- ['all' => true],
- // ...
-];
-```
-
-If you don't have a `config/bundles.php` file in your project, chances are that you're using an older Symfony version.
-In this case, you should have an `app/AppKernel.php` file instead. Edit such file:
-
-```php
-HTTPS),
- # and send no header to a less secure destination (HTTPS->HTTP).
- # If `strict-origin-when-cross-origin` is not supported, use `no-referrer` policy,
- # no referrer information is sent along with requests.
- referrer_policy:
- enabled: true
- policies:
- - 'no-referrer'
- - 'strict-origin-when-cross-origin'
-
- # forces HTTPS handling, don't combine with flexible mode
- # and make sure you have SSL working on your site before enabling this
-# forced_ssl:
-# hsts_max_age: 2592000 # 30 days
-# hsts_subdomains: true
-# redirect_status_code: 302 # default, switch to 301 for permanent redirects
-
- # flexible HTTPS handling, read the detailed config info
- # and make sure you have SSL working on your site before enabling this
-# flexible_ssl:
-# cookie_name: auth
-# unsecured_logout: false
-```
-
-## Configuration Detail
-
-### Content Security Policy:
-
-Using CSP you can set a policy which modern browsers understand and will honor. The policy contains many different
-directives; `default-src`, `script-src`, `object-src`, `style-src`, `img-src`, `media-src`, `frame-src`,
-`font-src`, `connect-src`, `base-uri`, `child-src`, `form-action`, `frame-ancestors`, `plugin-types`,
-`block-all-mixed-content`, `upgrade-insecure-requests`, `report-uri`, `manifest-src`.
-
-You can provide an array of directives per content type, except for `block-all-mixed-content` and
-`upgrade-insecure-requests` that only accept boolean values. Empty content
-types will inherit from `default-src`, specified content types will never inherit from `default-src`. Please see
-the [Content Security Policy 1.0](https://www.w3.org/TR/2012/CR-CSP-20121115/) and
-[Content Security Policy 2.0](https://www.w3.org/TR/2015/CR-CSP2-20150721/) specifications for details.
-
-Each directive should be a domain, URI or keyword. The keyword `'self'` will allow content from the same origin as
-the page. If you need to allow inline scripts or `eval()` you can use `'unsafe-inline'` and `'unsafe-eval'`.
-
-**WARNING:** By using `'unsafe-inline'` or `'unsafe-eval'` you're effectively disabling the XSS protection
-mechanism of CSP.
-
-Apart from content types, the policy also accepts `report-uri` which should be a URI where a browser can POST a
-[JSON payload](https://developer.mozilla.org/en-US/docs/Security/CSP/Using_CSP_violation_reports#Sample_violation_report)
-to whenever a policy directive is violated.
-
-An optional `content_types` key lets you restrict the Content Security Policy headers only on some HTTP
-response given their content type.
-
-Finally, an optional `hosts` key lets you configure which hostnames (e.g. `foo.example.org`)
-the CSP rule should be enforced on. If the list is empty (it is by default), all
-hostnames will use the CSP rule.
-
-```yaml
-nelmio_security:
- csp:
- enabled: true
- report_logger_service: logger
- hosts: []
- content_types: []
- enforce:
- # see full description below
- level1_fallback: true
- # only send directives supported by the browser, defaults to false
- # this is a port of https://github.com/twitter/secureheaders/blob/83a564a235c8be1a8a3901373dbc769da32f6ed7/lib/secure_headers/headers/policy_management.rb#L97
- browser_adaptive:
- enabled: false
- report-uri: '%router.request_context.base_url%/nelmio/csp/report'
- default-src: [ 'self' ]
- frame-src: [ 'https://www.youtube.com' ]
- script-src:
- - 'self'
- - 'unsafe-inline'
- img-src:
- - 'self'
- - facebook.com
- - flickr.com
- block-all-mixed-content: true # defaults to false, blocks HTTP content over HTTPS transport
- # upgrade-insecure-requests: true # defaults to false, upgrades HTTP requests to HTTPS transport
- report:
- # see full description below
- level1_fallback: true
- # only send directives supported by the browser, defaults to false
- # this is a port of https://github.com/twitter/secureheaders/blob/83a564a235c8be1a8a3901373dbc769da32f6ed7/lib/secure_headers/headers/policy_management.rb#L97
- browser_adaptive:
- enabled: true
- report-uri: '%router.request_context.base_url%/nelmio/csp/report'
- script-src:
- - 'self'
-```
-
-The above configuration would enforce the following policy:
-
-* Default is to allow from same origin as the page
-* Frames only from secure youtube connections
-* JavaScript from same origin and from inline `
-{% endcspscript %}
-
-// ...
-
-{% cspstyle %}
-
-{% endcspstyle %}
-```
-
-If you're not using Twig, you can use message digest with the `ContentSecurityPolicyListener`, it will automatically
-compute the message digest and add it to the response CSP header:
-
-```php
-
-$listener->addScript("");
-
-
-$listener->addStyle("");
-
-```
-
-#### Nonce for inline script handling
-
-Content-Security-Policy specification also proposes a nonce implementation for inlining. Nelmio Security Bundle
-comes out of the box with nonce functionality. Twig is natively supported.
-
-
-In your Twig template use the `csp_nonce` function to access the nonce for the current request and add it to the response
-CSP header. If you do not request a nonce, nonce will not be generated.
-
-```twig
-
-
-// ...
-
-
-```
-
-If you're not using Twig, you can use nonce functionality with the `ContentSecurityPolicyListener`:
-
-```php
-// generates a nonce at first time, returns the same nonce once generated
-$listener->getNonce('script');
-// or
-$listener->getNonce('style');
-```
-
-#### Reporting:
-
-Using the `report-uri` you can easily collect violation using the `ContentSecurityPolicyController`.
-Here's an configuration example using `routing.yml`:
-
-```yaml
-csp_report:
- path: /csp/report
- methods: [POST]
- defaults: { _controller: nelmio_security.csp_reporter_controller::indexAction }
-```
-
-This part of the configuration helps to filter noise collected by this endpoint:
-
-```yaml
-nelmio_security:
- csp:
- report_endpoint:
- log_level: "notice" # Use the appropriate log_level
- log_formatter: ~ # Declare a service name that must implement Nelmio\SecurityBundle\ContentSecurityPolicy\Violation\Log\LogFormatterInterface
- log_channel: ~ # Declare the channel to use with the logger
- filters:
- # Filter false positive reports given a domain list
- domains: true
- # Filter false positive reports given a scheme list
- schemes: true
- # Filter false positive reports given known browser bugs
- browser_bugs: true
- # Filter false positive reports given known injected scripts
- injected_scripts: true
- # You can add you custom filter rules by implementing Nelmio\SecurityBundle\ContentSecurityPolicy\Violation\Filter\NoiseDetectorInterface
- # and tag the service with "nelmio_security.csp_report_filter"
- dismiss:
- # A list of key-values that should be dismissed
- # A key is either a domain or a regular expression
- # A value is a source or an array of source. The '*' wilcard is accepted
- '/^data:/': 'script-src'
- '/^https?:\/\/\d+\.\d+\.\d+\.\d+(:\d+)*/': '*'
- 'maxcdn.bootstrapcdn.com': '*'
- 'www.gstatic.com': ['media-src', 'img-src']
-```
-
-### **Signed Cookies**:
-
-Ideally you should explicitly specify which cookies to sign. The reason for this is simple.
-Cookies are sent with each request. Signatures are often longer than the cookie values themselves,
-so signing everything would just needlessly slow down your app and increase bandwidth usage for
-your users.
-
-```yaml
-nelmio_security:
- signed_cookie:
- names: [test1, test2]
-```
-
-However, for simplicity reasons, and to start with a high security and optimize later, you can
-specify '*' as a cookie name to have all cookies signed automatically.
-
-```yaml
-nelmio_security:
- signed_cookie:
- names: ['*']
-```
-
-Additional, optional configuration settings:
-
-```yaml
-nelmio_security:
- signed_cookie:
- secret: this_is_very_secret # defaults to global %secret% parameter
- hash_algo: sha512 # defaults to sha256, see `hash_algos()` for available algorithms
-```
-
-### **Clickjacking Protection**:
-
-Most websites do not use frames and do not need to be frame-able. This is a common attack vector
-for which all current browsers (IE8+, Opera10.5+, Safari4+, Chrome4+ and Firefox3.7+) have a
-solution. An extra header sent by your site will tell the browser that it can not be displayed in
-a frame. Browsers react by showing a short explanation instead of the content, or a blank page.
-
-The valid values for the `X-Frame-Options` header are `DENY` (prevent framing from all pages) and
-`SAMEORIGIN` (prevent framing from all pages not on the same domain). Additionally this bundle
-supports the `ALLOW` option which skips the creation of the header for the matched URLs, if you
-want to allow a few URLs and then DENY everything else.
-
-One more option, as of yet [not well supported](https://developer.mozilla.org/en-US/docs/Web/HTTP/X-Frame-Options),
-is to use `ALLOW-FROM uri` where `uri` can be any origin URL, from
-`example.org` to `https://example.org:123/sub/path`. This lets you specify
-exactly which domain can embed your site, in case you have a multi-domain setup.
-
-Default configuration (deny everything):
-
-```yaml
-nelmio_security:
- clickjacking:
- paths:
- '^/.*': DENY
- content_types: []
- hosts: []
-```
-
-Allow list configuration (deny all but a few URLs):
-
-```yaml
-nelmio_security:
- clickjacking:
- paths:
- '^/iframes/': ALLOW
- '^/business/': 'ALLOW-FROM https://biz.example.org'
- '^/local/': SAMEORIGIN
- '^/.*': DENY
- content_types: []
- hosts: []
-```
-
-Apply to certain hosts:
-
-```yaml
-nelmio_security:
- clickjacking:
- paths:
- '^/iframes/': ALLOW
- '^/.*': DENY
- content_types: []
- hosts:
- - '^foo\.com$'
- - '\.example\.org$'
-```
-
-You can also of course only deny a few critical URLs, while leaving the rest alone:
-
-```yaml
-nelmio_security:
- clickjacking:
- paths:
- '^/message/write': DENY
- content_types: []
- hosts: []
-```
-
-An optional `content_types` key lets you restrict the X-Frame-Options header only on some HTTP
-response given their content type.
-
-### **External Redirects Detection**:
-
-This feature helps you detect and prevent redirects to external sites. This can easily happen
-by accident if you carelessly take query parameters as redirection target.
-
-You can log those (it's logged at warning level) by turning on logging:
-
-```yaml
-nelmio_security:
- external_redirects:
- log: true
-```
-
-You can abort (they are replaced by a 403 response) the redirects:
-
-```yaml
-nelmio_security:
- external_redirects:
- abort: true
-```
-
-Or you can override them, replacing the redirect's `Location` header by a route name or
-another URL:
-
-```yaml
-# redirect to the 'home' route
-nelmio_security:
- external_redirects:
- override: home
-```
-```yaml
-# redirect to another URL
-nelmio_security:
- external_redirects:
- override: /foo
-```
-
-If you want to display the URL that was blocked on the overriding page you can
-specify the `forward_as` parameter, which defines which query parameter will
-receive the URL. For example using the config below, doing a redirect to
-`http://example.org/` will be overridden to `/external-redirect?redirUrl=http://example.org/`.
-
-```yaml
-# redirect and forward the overridden URL
-nelmio_security:
- external_redirects:
- override: /external-redirect
- forward_as: redirUrl
-```
-
-Since it's quite common to have to redirect outside the website for legit reasons,
-typically OAuth logins and such, you can allow a few domain names. All their subdomains
-will be allowed as well, so you can allow your own website's subdomains
-if needed.
-
-```yaml
-nelmio_security:
- external_redirects:
- abort: true
- allow_list:
- - twitter.com
- - facebook.com
-```
-
-### **Forced HTTPS/SSL Handling**:
-
-By default, this option forces your entire site to use SSL, always. It redirect all users
-reaching the site with a http:// URL to a https:// URL with a 302 response.
-
-The base configuration for this is the following:
-
-```yaml
-nelmio_security:
- forced_ssl: ~
-```
-
-If you turn this option on, it's recommended to also set your session cookie to be secure,
-and all other cookies you send for that matter. You can do the former using:
-
-```yaml
-framework:
- session:
- cookie_secure: true
-```
-
-To keep a few URLs from being force-redirected to SSL you can define an allowed list of regular
-expressions:
-
-```yaml
-nelmio_security:
- forced_ssl:
- enabled: true
- allow_list:
- - ^/unsecure/
-```
-
-To restrict the force-redirects to some hostnames only you can define a list of hostnames
-as regular expressions:
-
-```yaml
-nelmio_security:
- forced_ssl:
- enabled: true
- hosts:
- - ^\.example\.org$
-```
-
-To change the way the redirect is done to a permanent redirect for example, you can set:
-
-```yaml
-nelmio_security:
- forced_ssl:
- enabled: true
- redirect_status_code: 301
-```
-
-Then if you want to push it further, you can enable
-[HTTP Strict Transport Security (HSTS)](http://tools.ietf.org/html/draft-hodges-strict-transport-sec-02).
-This is basically sending a header to tell the browser that your site must always be
-accessed using SSL. If a user enters a http:// URL, the browser will convert it to https://
-automatically, and will do so before making any request, which prevents man-in-the-middle
-attacks.
-
-The browser will cache the value for as long as the specified `hsts_max_age` (in seconds), and if
-you turn on the `hsts_subdomains` option, the behavior will be applied to all subdomains as well.
-
-```yaml
-nelmio_security:
- forced_ssl:
- hsts_max_age: 2592000 # 30 days
- hsts_subdomains: true
-```
-
-You can also tell the browser to add your site to the list of known HSTS sites, by enabling
-`hsts_preload`. Once your site has appeared in the Chrome and Firefox preload lists, then new
-users who come to your site will already be redirected to HTTPS URLs.
-
-```yaml
-nelmio_security:
- forced_ssl:
- hsts_max_age: 31536000 # 1 year
- hsts_preload: true
-```
-
-> **Note:** A value of at least 1 year is currently required by [Chrome](https://hstspreload.org/)
-> and [Firefox](https://blog.mozilla.org/security/2012/11/01/preloading-hsts/).
-> `hsts_subdomains` must also be enabled for preloading to work.
-
-You can speed up the inclusion process by submitting your site to the [HSTS Preload List](https://hstspreload.org/).
-
-A small word of caution: While HSTS is great for security, it means that if the browser
-can not establish your SSL certificate is valid, it will not allow the user to query your site.
-That just means you should be careful and renew your certificate in due time.
-
-Note: HSTS presently (Feb. 2018) works in Firefox 4+, Chrome 4+, Opera 12+, IE 11+, Edge 12+ and Safari 7+.
- Check [caniuse](http://caniuse.com/#feat=stricttransportsecurity) for HSTS support in other browsers.
-
-### **Flexible HTTPS/SSL Handling**:
-
-The best way to handle SSL securely is to enable it for your entire site.
-
-However in some cases this is not desirable, be it for caching or performance reasons,
-or simply because most visitors of your site are anonymous and don't benefit much from the
-added privacy and security of SSL.
-
-If you don't want to enable SSL across the board, you need to avoid that people on insecure
-networks (typically open Wi-Fi) get their session cookie stolen by sending it non-encrypted.
-The way to achieve this is to set your session cookie to be secure as such - but don't do
-it just yet, keep reading to the end.
-
-```yaml
-framework:
- session:
- cookie_secure: true
-```
-
-If you use the remember-me functionality, you would also mark that one as secure:
-
-```yaml
-security:
- firewalls:
- somename:
- remember_me:
- secure: true
-```
-
-Now if you do this, you have two problems. First, insecure pages will not be able to use
-the session anymore, which can be inconvenient. Second, if a logged in user gets to a
-non-HTTPS page of your site, it is seen as anonymous since his browser will not send the
-session cookie. To fix this, this bundle sets a new insecure cookie
-(`flexible_ssl.cookie_name`, defaults to `auth`) once a user logs in. That way, if any page
-is accessed insecurely by a logged in user, he is redirected to the secure version of the
-page, and his session is then visible to the framework.
-
-Enabling the `flexible_ssl` option of the NelmioSecurityBundle will make sure that
-logged-in users are always seeing secure pages, and it will make sure their session cookie
-is secure, but anonymous users will still be able to have an insecure session, if you need
-to use it to store non critical data like language settings and whatnot. The remember-me
-cookie will also be made always secure, even if you leave the setting to false.
-
-```yaml
-nelmio_security:
- flexible_ssl:
- cookie_name: auth
- unsecured_logout: false
-```
-
-You have to configure one more thing in your security configuration though: every firewall
-should have our logout listener added, so that the special `auth` cookie can be cleared when
-users log out. You can do it as such:
-
-```yaml
-security:
- firewalls:
- somename:
- # ...
- logout:
- handlers:
- - nelmio_security.flexible_ssl_listener
-```
-
-On logout, if you would like users to be redirected to an unsecure page set ``unsecured_logout``
-to true.
-
-### Content Type Sniffing
-
-Disables the content type sniffing for script resources. Forces the browser to only execute script files with valid
-content type headers. This is a non-standard header from Microsoft, more information can be found in
-[their documentation at MSDN](http://msdn.microsoft.com/en-us/library/ie/gg622941.aspx).
-
-```yaml
-nelmio_security:
- content_type:
- nosniff: true
-```
-
-### XSS Protection
-
-Enables or disables Microsoft XSS Protection on compatible browsers.
-This is a non-standard header from Microsoft, more information can be found in
-[their documentation at MSDN](http://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx).
-
-```yaml
-nelmio_security:
- xss_protection:
- enabled: true
- mode_block: true
- report_uri: '%router.request_context.base_url%/nelmio/xss/report'
-```
-
-### Referrer Policy
-
-Adds `Referrer-Policy` header to control the `Referer` header that is added
-to requests made from your site, and for navigations away from your site by browsers.
-
-You can specify multiple [referrer policies](https://www.w3.org/TR/referrer-policy/#referrer-policies).
-The order of the policies is important. Browser will choose only the last policy they understand.
-For example older browsers don’t understand the `strict-origin-when-cross-origin` policy.
-A site can specify a `no-referrer` policy followed by a `strict-origin-when-cross-origin` policy:
-older browsers will ignore the unknown `strict-origin-when-cross-origin` value and use `no-referrer`,
-while newer browsers will use `strict-origin-when-cross-origin` because it is the last to be processed.
-
-A referrer policy is:
- * [`no-referrer`](https://www.w3.org/TR/referrer-policy/#referrer-policy-no-referrer),
- * [`no-referrer-when-downgrade`](https://www.w3.org/TR/referrer-policy/#referrer-policy-no-referrer-when-downgrade),
- * [`same-origin`](https://www.w3.org/TR/referrer-policy/#referrer-policy-same-origin),
- * [`origin`](https://www.w3.org/TR/referrer-policy/#referrer-policy-origin),
- * [`strict-origin`](https://www.w3.org/TR/referrer-policy/#referrer-policy-strict-origin),
- * [`origin-when-cross-origin`](https://www.w3.org/TR/referrer-policy/#referrer-policy-origin-when-cross-origin),
- * [`strict-origin-when-cross-origin`](https://www.w3.org/TR/referrer-policy/#referrer-policy-strict-origin-when-cross-origin),
- * [`unsafe-url`](https://www.w3.org/TR/referrer-policy/#referrer-policy-unsafe-url),
- * [the empty string](https://www.w3.org/TR/referrer-policy/#referrer-policy-empty-string).
-
-For better security of your site please use `no-referrer`, `same-origin`, `strict-origin` or `strict-origin-when-cross-origin`.
-
-```yaml
-nelmio_security:
- referrer_policy:
- enabled: true
- policies:
- - 'no-referrer'
- - 'strict-origin-when-cross-origin'
-```
-
## License
Released under the MIT License, see LICENSE.
+
+[1]: https://symfony.com/doc/current/setup/flex.html
+[2]: src/Resources/doc/index.rst
diff --git a/src/Resources/doc/index.rst b/src/Resources/doc/index.rst
new file mode 100644
index 0000000..54ff28f
--- /dev/null
+++ b/src/Resources/doc/index.rst
@@ -0,0 +1,912 @@
+NelmioSecurityBundle
+====================
+
+The NelmioSecurityBundle provides additional security features for your Symfony application.
+
+Installation
+------------
+
+Require the ``nelmio/security-bundle`` package in your composer.json and update
+your dependencies:
+
+.. code-block:: terminal
+
+ $ composer require nelmio/security-bundle
+
+The bundle should be automatically enabled by `Symfony Flex`_. If you don't use
+Flex, you'll need to manually enable the bundle by adding the following line in
+the ``config/bundles.php`` file of your project::
+
+ ['all' => true],
+ // ...
+ ];
+
+If you don't have a ``config/bundles.php`` file in your project, chances are that
+you're using an older Symfony version. In this case, you should have an
+``app/AppKernel.php`` file instead. Edit such file:
+
+ HTTPS),
+ # and send no header to a less secure destination (HTTPS->HTTP).
+ # If ``strict-origin-when-cross-origin`` is not supported, use ``no-referrer`` policy,
+ # no referrer information is sent along with requests.
+ referrer_policy:
+ enabled: true
+ policies:
+ - 'no-referrer'
+ - 'strict-origin-when-cross-origin'
+
+ # forces HTTPS handling, don't combine with flexible mode
+ # and make sure you have SSL working on your site before enabling this
+ # forced_ssl:
+ # hsts_max_age: 2592000 # 30 days
+ # hsts_subdomains: true
+ # redirect_status_code: 302 # default, switch to 301 for permanent redirects
+
+ # flexible HTTPS handling, read the detailed config info
+ # and make sure you have SSL working on your site before enabling this
+ # flexible_ssl:
+ # cookie_name: auth
+ # unsecured_logout: false
+
+Content Security Policy
+-----------------------
+
+Using CSP you can set a policy which modern browsers understand and will honor.
+The policy contains many different directives; ``default-src``, ``script-src``,
+``object-src``, ``style-src``, ``img-src``, ``media-src``, ``frame-src``,
+``font-src``, ``connect-src``, ``base-uri``, ``child-src``, ``form-action``,
+``frame-ancestors``, ``plugin-types``, ``block-all-mixed-content``,
+``upgrade-insecure-requests``, ``report-uri``, ``manifest-src``.
+
+You can provide an array of directives per content type, except for ``block-all-mixed-content``
+and ``upgrade-insecure-requests`` that only accept boolean values. Empty content
+types will inherit from ``default-src``, specified content types will never inherit
+from ``default-src``. Please see the `Content Security Policy 1.0`_ and
+`Content Security Policy 2.0`_ specifications for details.
+
+Each directive should be a domain, URI or keyword. The keyword ``'self'`` will
+allow content from the same origin as the page. If you need to allow inline
+scripts or ``eval()`` you can use ``'unsafe-inline'`` and ``'unsafe-eval'``.
+
+.. caution::
+
+ By using ``'unsafe-inline'`` or ``'unsafe-eval'`` you're effectively
+ disabling the XSS protection mechanism of CSP.
+
+Apart from content types, the policy also accepts ``report-uri`` which should be
+a URI where a browser can POST a `JSON payload`_ to whenever a policy directive
+is violated.
+
+An optional ``content_types`` key lets you restrict the Content Security Policy
+headers only on some HTTP response given their content type.
+
+Finally, an optional ``hosts`` key lets you configure which hostnames (e.g. ``foo.example.org``)
+the CSP rule should be enforced on. If the list is empty (it is by default), all
+hostnames will use the CSP rule.
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ csp:
+ enabled: true
+ report_logger_service: logger
+ hosts: []
+ content_types: []
+ enforce:
+ # see full description below
+ level1_fallback: true
+ # only send directives supported by the browser, defaults to false
+ # this is a port of https://github.com/twitter/secureheaders/blob/83a564a235c8be1a8a3901373dbc769da32f6ed7/lib/secure_headers/headers/policy_management.rb#L97
+ browser_adaptive:
+ enabled: false
+ report-uri: '%router.request_context.base_url%/nelmio/csp/report'
+ default-src: [ 'self' ]
+ frame-src: [ 'https://www.youtube.com' ]
+ script-src:
+ - 'self'
+ - 'unsafe-inline'
+ img-src:
+ - 'self'
+ - facebook.com
+ - flickr.com
+ block-all-mixed-content: true # defaults to false, blocks HTTP content over HTTPS transport
+ # upgrade-insecure-requests: true # defaults to false, upgrades HTTP requests to HTTPS transport
+ report:
+ # see full description below
+ level1_fallback: true
+ # only send directives supported by the browser, defaults to false
+ # this is a port of https://github.com/twitter/secureheaders/blob/83a564a235c8be1a8a3901373dbc769da32f6ed7/lib/secure_headers/headers/policy_management.rb#L97
+ browser_adaptive:
+ enabled: true
+ report-uri: '%router.request_context.base_url%/nelmio/csp/report'
+ script-src:
+ - 'self'
+
+The above configuration would enforce the following policy:
+
+* Default is to allow from same origin as the page
+* Frames only from secure YouTube connections
+* JavaScript from same origin and from inline ``
+ {% endcspscript %}
+
+ {# ... #}
+
+ {% cspstyle %}
+
+ {% endcspstyle %}
+
+If you're not using Twig, you can use message digest with the
+``ContentSecurityPolicyListener``, it will automatically compute the message
+digest and add it to the response CSP header::
+
+ $listener->addScript("");
+
+
+ $listener->addStyle("");
+
+Nonce for inline script handling
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Content-Security-Policy specification also proposes a nonce implementation for
+inlining. Nelmio Security Bundle comes out of the box with nonce functionality.
+Twig is natively supported.
+
+In your Twig template use the ``csp_nonce`` function to access the nonce for the
+current request and add it to the response CSP header. If you do not request a
+nonce, nonce will not be generated.
+
+.. code-block:: html+twig
+
+
+
+ {# ... #}
+
+
+
+If you're not using Twig, you can use nonce functionality with the ``ContentSecurityPolicyListener``::
+
+ // generates a nonce at first time, returns the same nonce once generated
+ $listener->getNonce('script');
+ // or
+ $listener->getNonce('style');
+
+Reporting
+~~~~~~~~~
+
+Using the ``report-uri`` you can easily collect violation using the ``ContentSecurityPolicyController``.
+Here's an configuration example using ``routing.yml``:
+
+.. code-block:: yaml
+
+ # config/routes.yaml
+ csp_report:
+ path: /csp/report
+ methods: [POST]
+ defaults: { _controller: nelmio_security.csp_reporter_controller::indexAction }
+
+This part of the configuration helps to filter noise collected by this endpoint:
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ csp:
+ report_endpoint:
+ log_level: "notice" # Use the appropriate log_level
+ log_formatter: ~ # Declare a service name that must implement Nelmio\SecurityBundle\ContentSecurityPolicy\Violation\Log\LogFormatterInterface
+ log_channel: ~ # Declare the channel to use with the logger
+ filters:
+ # Filter false positive reports given a domain list
+ domains: true
+ # Filter false positive reports given a scheme list
+ schemes: true
+ # Filter false positive reports given known browser bugs
+ browser_bugs: true
+ # Filter false positive reports given known injected scripts
+ injected_scripts: true
+ # You can add you custom filter rules by implementing Nelmio\SecurityBundle\ContentSecurityPolicy\Violation\Filter\NoiseDetectorInterface
+ # and tag the service with "nelmio_security.csp_report_filter"
+ dismiss:
+ # A list of key-values that should be dismissed
+ # A key is either a domain or a regular expression
+ # A value is a source or an array of source. The '*' wilcard is accepted
+ '/^data:/': 'script-src'
+ '/^https?:\/\/\d+\.\d+\.\d+\.\d+(:\d+)*/': '*'
+ 'maxcdn.bootstrapcdn.com': '*'
+ 'www.gstatic.com': ['media-src', 'img-src']
+
+Signed Cookies
+--------------
+
+Ideally you should explicitly specify which cookies to sign. The reason for this
+is simple. Cookies are sent with each request. Signatures are often longer than
+the cookie values themselves, so signing everything would just needlessly slow
+down your app and increase bandwidth usage for your users.
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ signed_cookie:
+ names: [test1, test2]
+
+However, for simplicity reasons, and to start with a high security and optimize
+later, you can specify ``*`` as a cookie name to have all cookies signed automatically.
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ signed_cookie:
+ names: ['*']
+
+Additional, optional configuration settings:
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ signed_cookie:
+ secret: this_is_very_secret # defaults to global %secret% parameter
+ hash_algo: sha512 # defaults to sha256, see ``hash_algos()`` for available algorithms
+
+Clickjacking Protection
+-----------------------
+
+Most websites do not use frames and do not need to be frame-able. This is a
+common attack vector for which all current browsers (IE8+, Opera10.5+,
+Safari4+, Chrome4+ and Firefox3.7+) have a solution. An extra header sent by
+your site will tell the browser that it can not be displayed in a frame.
+Browsers react by showing a short explanation instead of the content, or a blank page.
+
+The valid values for the ``X-Frame-Options`` header are ``DENY``(prevent framing
+from all pages) and ``SAMEORIGIN`` (prevent framing from all pages not on the
+same domain). Additionally this bundle supports the ``ALLOW`` option which
+skips the creation of the header for the matched URLs, if you want to allow a
+few URLs and then DENY everything else.
+
+One more option, as of yet `not well supported`_, is to use ``ALLOW-FROM uri``
+where ``uri`` can be any origin URL, from ``example.org`` to
+``https://example.org:123/sub/path``. This lets you specify exactly which domain
+can embed your site, in case you have a multi-domain setup.
+
+Default configuration (deny everything):
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ clickjacking:
+ paths:
+ '^/.*': DENY
+ content_types: []
+ hosts: []
+
+Allow list configuration (deny all but a few URLs):
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ clickjacking:
+ paths:
+ '^/iframes/': ALLOW
+ '^/business/': 'ALLOW-FROM https://biz.example.org'
+ '^/local/': SAMEORIGIN
+ '^/.*': DENY
+ content_types: []
+ hosts: []
+
+Apply to certain hosts:
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ clickjacking:
+ paths:
+ '^/iframes/': ALLOW
+ '^/.*': DENY
+ content_types: []
+ hosts:
+ - '^foo\.com$'
+ - '\.example\.org$'
+
+You can also of course only deny a few critical URLs, while leaving the rest alone:
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ clickjacking:
+ paths:
+ '^/message/write': DENY
+ content_types: []
+ hosts: []
+
+An optional ``content_types`` key lets you restrict the X-Frame-Options header
+only on some HTTP response given their content type.
+
+External Redirects Detection
+----------------------------
+
+This feature helps you detect and prevent redirects to external sites. This can
+easily happen by accident if you carelessly take query parameters as redirection target.
+
+You can log those (it's logged at warning level) by turning on logging:
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ external_redirects:
+ log: true
+
+You can abort (they are replaced by a 403 response) the redirects:
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ external_redirects:
+ abort: true
+
+Or you can override them, replacing the redirect's ``Location`` header by a
+route name or another URL:
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ external_redirects:
+ # redirect to the 'home' route
+ override: home
+ # use this to redirect to another URL
+ # override: /foo
+
+If you want to display the URL that was blocked on the overriding page you can
+specify the ``forward_as`` parameter, which defines which query parameter will
+receive the URL. For example using the config below, doing a redirect to
+``http://example.org/`` will be overridden to ``/external-redirect?redirUrl=http://example.org/``.
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ external_redirects:
+ # redirect and forward the overridden URL
+ override: /external-redirect
+ forward_as: redirUrl
+
+Since it's quite common to have to redirect outside the website for legit
+reasons, typically OAuth logins and such, you can allow a few domain names. All
+their subdomains will be allowed as well, so you can allow your own website's
+subdomains if needed.
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ external_redirects:
+ abort: true
+ allow_list:
+ - twitter.com
+ - facebook.com
+
+Forced HTTPS/SSL Handling
+-------------------------
+
+By default, this option forces your entire site to use SSL, always. It redirect
+all users reaching the site with a http:// URL to a https:// URL with a 302 response.
+
+The base configuration for this is the following:
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ forced_ssl: ~
+
+If you turn this option on, it's recommended to also set your session cookie to
+be secure, and all other cookies you send for that matter. You can do the former using:
+
+.. code-block:: yaml
+
+ # config/packages/framework.yaml
+ framework:
+ session:
+ cookie_secure: true
+
+To keep a few URLs from being force-redirected to SSL you can define an allowed
+list of regular expressions:
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ forced_ssl:
+ enabled: true
+ allow_list:
+ - ^/unsecure/
+
+To restrict the force-redirects to some hostnames only you can define a list of
+hostnames as regular expressions:
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ forced_ssl:
+ enabled: true
+ hosts:
+ - ^\.example\.org$
+
+To change the way the redirect is done to a permanent redirect for example, you can set:
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ forced_ssl:
+ enabled: true
+ redirect_status_code: 301
+
+Then if you want to push it further, you can enable `HTTP Strict Transport Security (HSTS)`.
+This is basically sending a header to tell the browser that your site must always
+be accessed using SSL. If a user enters a http:// URL, the browser will convert it
+to https:// automatically, and will do so before making any request, which prevents
+man-in-the-middle attacks.
+
+The browser will cache the value for as long as the specified ``hsts_max_age``
+(in seconds), and if you turn on the ``hsts_subdomains`` option, the behavior
+will be applied to all subdomains as well.
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ forced_ssl:
+ hsts_max_age: 2592000 # 30 days
+ hsts_subdomains: true
+
+You can also tell the browser to add your site to the list of known HSTS sites,
+by enabling ``hsts_preload``. Once your site has appeared in the Chrome and
+Firefox preload lists, then new users who come to your site will already be
+redirected to HTTPS URLs.
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ forced_ssl:
+ hsts_max_age: 31536000 # 1 year
+ hsts_preload: true
+
+.. note::
+
+ A value of at least 1 year is currently `required by Chrome`_ and
+ `also required by Firefox`_. ``hsts_subdomains`` must also be enabled for
+ preloading to work.
+
+You can speed up the inclusion process by submitting your site to the `HSTS Preload List`_.
+
+A small word of caution: While HSTS is great for security, it means that if the
+browser can not establish your SSL certificate is valid, it will not allow the
+user to query your site. That just means you should be careful and renew your
+certificate in due time.
+
+.. tip::
+
+ Check `Can I use HSTS?`_ for the full information about its support in browsers.
+
+Flexible HTTPS/SSL Handling
+---------------------------
+
+The best way to handle SSL securely is to enable it for your entire site.
+
+However in some cases this is not desirable, be it for caching or performance
+reasons, or simply because most visitors of your site are anonymous and don't
+benefit much from the added privacy and security of SSL.
+
+If you don't want to enable SSL across the board, you need to avoid that people
+on insecure networks (typically open Wi-Fi) get their session cookie stolen by
+sending it non-encrypted. The way to achieve this is to set your session cookie
+to be secure as such - but don't do it just yet, keep reading to the end.
+
+.. code-block:: yaml
+
+ # config/packages/framework.yaml
+ framework:
+ session:
+ cookie_secure: true
+
+If you use the remember-me functionality, you would also mark that one as secure:
+
+.. code-block:: yaml
+
+ # config/packages/security.yaml
+ security:
+ firewalls:
+ somename:
+ remember_me:
+ secure: true
+
+Now if you do this, you have two problems. First, insecure pages will not be
+able to use the session anymore, which can be inconvenient. Second, if a logged
+in user gets to a non-HTTPS page of your site, it is seen as anonymous since
+his browser will not send the session cookie. To fix this, this bundle sets a
+new insecure cookie(``flexible_ssl.cookie_name``, defaults to ``auth``) once a
+user logs in. That way, if any page is accessed insecurely by a logged in user,
+he is redirected to the secure version of the page, and his session is then
+visible to the framework.
+
+Enabling the ``flexible_ssl`` option of the NelmioSecurityBundle will make sure
+that logged-in users are always seeing secure pages, and it will make sure
+their session cookie is secure, but anonymous users will still be able to have
+an insecure session, if you need to use it to store non critical data like
+language settings and whatnot. The remember-me cookie will also be made always
+secure, even if you leave the setting to false.
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ flexible_ssl:
+ cookie_name: auth
+ unsecured_logout: false
+
+You have to configure one more thing in your security configuration though:
+every firewall should have our logout listener added, so that the special
+``auth`` cookie can be cleared when users log out. You can do it as such:
+
+.. code-block:: yaml
+
+ # config/packages/security.yaml
+ security:
+ firewalls:
+ somename:
+ # ...
+ logout:
+ handlers:
+ - nelmio_security.flexible_ssl_listener
+
+On logout, if you would like users to be redirected to an unsecure page set
+``unsecured_logout`` to true.
+
+Content Type Sniffing
+---------------------
+
+Disables the content type sniffing for script resources. Forces the browser to only execute script files with valid
+content type headers. This requires using `a non-standard nosniff header from Microsoft`_.
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ content_type:
+ nosniff: true
+
+XSS Protection
+--------------
+
+Enables or disables Microsoft XSS Protection on compatible browsers.
+This requires using `a non-standard X-XSS-Protection header from Microsoft`_.
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ xss_protection:
+ enabled: true
+ mode_block: true
+ report_uri: '%router.request_context.base_url%/nelmio/xss/report'
+
+Referrer Policy
+---------------
+
+Adds ``Referrer-Policy`` header to control the ``Referer`` header that is added
+to requests made from your site, and for navigations away from your site by browsers.
+
+You can specify multiple `referrer policies`_. The order of the policies is
+important. Browser will choose only the last policy they understand. For
+example older browsers don't understand the ``strict-origin-when-cross-origin``
+policy. A site can specify a ``no-referrer`` policy followed by a
+``strict-origin-when-cross-origin`` policy: older browsers will ignore the
+unknown ``strict-origin-when-cross-origin`` value and use ``no-referrer``,
+while newer browsers will use ``strict-origin-when-cross-origin`` because it is
+the last to be processed.
+
+These are the valid referrer policies:
+
+* `no-referrer `_
+* `no-referrer-when-downgrade `_
+* `same-origin `_
+* `origin `_
+* `strict-origin `_
+* `origin-when-cross-origin `_
+* `strict-origin-when-cross-origin `_
+* `unsafe-url `_
+* `an empty string `_
+
+For better security of your site please use ``no-referrer``, ``same-origin``,
+``strict-origin`` or ``strict-origin-when-cross-origin``.
+
+.. code-block:: yaml
+
+ # config/packages/nelmio_security.yaml
+ nelmio_security:
+ referrer_policy:
+ enabled: true
+ policies:
+ - 'no-referrer'
+ - 'strict-origin-when-cross-origin'
+
+.. _`Symfony Flex`: https://symfony.com/doc/current/setup/flex.html
+.. _`Content Security Policy 1.0`: https://www.w3.org/TR/2012/CR-CSP-20121115/
+.. _`Content Security Policy 2.0`: https://www.w3.org/TR/2015/CR-CSP2-20150721/
+.. _`JSON payload`: https://developer.mozilla.org/en-US/docs/Security/CSP/Using_CSP_violation_reports#Sample_violation_report
+.. _`Twitter SecureHeaders library`: https://github.com/twitter/secureheaders
+.. _`not well supported`: https://developer.mozilla.org/en-US/docs/Web/HTTP/X-Frame-Options
+.. _`HTTP Strict Transport Security (HSTS)`: http://tools.ietf.org/html/draft-hodges-strict-transport-sec-02
+.. _`required by Chrome`: https://hstspreload.org/
+.. _`also required by Firefox`: https://blog.mozilla.org/security/2012/11/01/preloading-hsts/
+.. _`HSTS Preload List`: https://hstspreload.org/
+.. _`Can I use HSTS?`: http://caniuse.com/#feat=stricttransportsecurity
+.. _`a non-standard nosniff header from Microsoft`: http://msdn.microsoft.com/en-us/library/ie/gg622941.aspx
+.. _`a non-standard X-XSS-Protection header from Microsoft`: http://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx
+.. _`referrer policies`: https://www.w3.org/TR/referrer-policy/#referrer-policies