Add a default Content-Security-Policy and clickjacking defence to core

Created on 27 June 2015, about 9 years ago
Updated 29 May 2024, about 2 months ago

Problem/Motivation

Content Security Policy is a browser feature that helps prevent XSS and other attacks by sending a header that informs the browser of trusted sources for page resources.

In modern browsers, it replaces the use of X-Frame-Options with the directive frame-ancestors.

Additional directives such as default-src, script-src, and style-src may be difficult to provide default a value in core such as 'self' because it will block third-party or inline resources that site builders expect to load.

For CSP spec see:
- http://www.w3.org/TR/CSP/
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Securi...
- https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet

The contrib modules Content-Security-Policy β†’ and Security Kit β†’ provide a user interface for configuring a site's Content Security Policy headers, but core should provide a reasonable default policy for sites.

The Reporting API β†’ contrib module provides a local endpoint for violation reports, and hosted services for monitoring violations are also available.
The potential for abuse of violation reporting (DoS attacks, bogus data, etc) is outlined at https://www.virtuesecurity.com/blog/abusing-csp-violation-reporting/

Proposed resolution

Implement a basic CSP header for Drupal core configurable through a service parameter, which replaces X-Frame-Options: SAMEORIGIN

Content-Security-Policy: frame-ancestors 'self'

For backwards compatibility of sites that have altered X-Frame-Options from the value set by core and not set a Content Security Policy header, translate the value to an equivalent Content-Security-Policy: frame-ancestors value and throw a deprecation warning.

Remaining tasks

  • Service parameter name: http.response.content_security_policy (like http.response.debug_cacheability_headers) or csp.config (like cors.config) or ?
  • Should a X-Frame-Options header present on a response be removed in 11.x, since browsers will ignore it when CSP is present?
  • Decide on additional directives to add by default, such as script-src * 'unsafe-inline'; object-src 'none'
  • Create followup to remove compatibility layer in 12.0.0, and set default policy in core.services.yml, and default.services.yml

User interface changes

None

API changes

A new services parameter http.response.content_security_policy has two properties, report_only and enforced, for setting a site's default Content Security Policies.
Modules can modify or replace the default policy headers by implementing a response subscriber.

Draft Change Record

Drupal 11.0 and earlier set a X-Frame-Options: SAMEORIGIN header by default, which can be overridden or removed by other modules.

In Drupal 11.1 and later, this will be replaced with a Content Security Policy header that includes frame-ancestors 'self'. To change the value of the Content Security Policy header, edit the http.response.content_security_policy service parameter.

For backwards compatibility on sites that have customized the X-Frame-Options header, Drupal 11.x will translate it to an equivalent Content-Security-Policy header, unless a customized policy has been defined in the services parameter.
Starting in Drupal 12, any X-Frame-Options header will be ignored, and Content-Security-Policy: frame-ancestors 'self' will be set by default.

πŸ“Œ Task
Status

Needs work

Version

11.0 πŸ”₯

Component
BaseΒ  β†’

Last updated about 9 hours ago

Created by

πŸ‡ΊπŸ‡ΈUnited States pwolanin

Live updates comments and jobs are added and updated live.
  • Security improvements

    It makes Drupal less vulnerable to abuse or misuse. Note, this is the preferred tag, though the Security tag has a large body of issues tagged to it. Do NOT publicly disclose security vulnerabilities; contact the security team instead. Anyone (whether security team or not) can apply this tag to security improvements that do not directly present a vulnerability e.g. hardening an API to add filtering to reduce a common mistake in contributed modules.

  • Needs change record

    A change record needs to be drafted before an issue is committed. Note: Change records used to be called change notifications.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡ΊπŸ‡ΈUnited States bkosborne New Jersey, USA

    I guess the X-Frame-Options header that core adds via FinishResponseSubscriber should also be removed when this is done. The "frame-ancestors" directive in the CSP header is well supported and obsoletes X-Frame-Options.

  • πŸ‡¨πŸ‡¦Canada gapple

    With IE no longer being supported, core could replace its default X-Frame-Options: SAMEORIGIN with Content-Security-Policy: frame-ancestors 'self'. Starting to always add a default CSP header could cause problems for a site that sets X-Frame-Options: DENY though. (It looks like IE was the only browser to support ALLOW-FROM).

    A possible transition is:
    [11.1] Add a late-subscriber that translates x-frame-options to a CSP frame-ancestors if the response does not have a CSP header (assume if a CSP header is set but does not include frame-ancestors, then it was intended to allow any frame parent). Issue a deprecation warning if the response has a value other than X-Frame-Options: SAMEORIGIN to notify users to use CSP instead.
    [12.0] Remove the late subscriber, and replace X-Frame-Options with a static CSP policy that includes frame-ancestors 'self'. A site that uses the Content-Security-Policy module, SecKit, or a custom listener to set the CSP header will override this default value.

    My suggestion for a minimal static policy that core can add by default:

      Content-Security-Policy: script-src * 'unsafe-inline'; object-src 'none'; frame-ancestors 'self'
    

    The simplest way to allow modifying the default CSP (or adding a CSP-Report-Only), would be to have a container parameter. Users wanting a more flexible implementation can use the CSP module.

  • Pipeline finished with Failed
    4 months ago
    Total: 692s
    #136140
  • Pipeline finished with Failed
    4 months ago
    Total: 195s
    #136173
  • Status changed to Needs review 4 months ago
  • πŸ‡¨πŸ‡¦Canada gapple

    A slightly rough MR:
    - Introduce a new service parameter for setting static CSP values
    - A late acting response subscriber will translate X-Frame-Options to Content-Secutity-Policy: frame-ancestors
    - If a CSP policy is set (via service parameter, or another module like CSP or seckit), then that value is not changed.
    - The X-Frame-Options header is always removed - either it's being replaced by core with an equivalent CSP policy, or we assume that the CSP policy set by the user has their desired frame-ancestors value (including the option of being omitted).
    - If X-Frame-Options is not set to SAMEORIGIN, then a deprecation warning is issued to use CSP to set the value. (If the value is still the default SAMEORIGIN, then a future version of Drupal changing to frame-ancestors 'self' will not change browser behaviour).
    - ALLOW-FROM is ignored by modern browsers (and equivalent to not sending the X-Frame-Options header), but is translated to a CSP value if used.

    In a future version of Drupal:
    - The service parameter can be set to a default enforced CSP value
    - The late acting event subscriber can be completely removed
    - Core can stop setting X-Frame-Options
    - Modules (such as CSP or seckit) will still override core's default (now static) value.

    Why the CSP policy value:
    - script-src * 'unsafe-inline' will only block eval(). Not including 'unsafe-inline' would have the potential to break existing sites (and hopefully its presence leads people to explore making sure it's not required...)
    - object-src 'none' is recommended to block legacy HTML elements
    - frame-ancestors replaces X-Frame-Options
    - I don't think there's other values that can safely be added as a default enforced policy directive without a reasonable risk of negatively affecting some sites. (maybe base-uri 'self'?)

  • Status changed to Needs work 4 months ago
  • The Needs Review Queue Bot β†’ tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

    This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

    Consult the Drupal Contributor Guide β†’ to find step-by-step guides for working with issues.

  • Assigned to gapple
  • πŸ‡¨πŸ‡¦Canada gapple

    Update issue summary

  • Pipeline finished with Canceled
    2 months ago
    Total: 353s
    #176273
  • Pipeline finished with Failed
    2 months ago
    Total: 178s
    #176277
  • Issue was unassigned.
  • Status changed to Needs review 2 months ago
  • πŸ‡¨πŸ‡¦Canada gapple

    Rebased and fixed the bot's previous issue.

    In my previous comment I wasn't sure of the core dev timeline, but this looks like it's something that could be put in 10.4, with the compatibility later removed in 11.0.0.

  • Pipeline finished with Failed
    2 months ago
    Total: 871s
    #176279
  • Pipeline finished with Failed
    2 months ago
    Total: 870s
    #177064
  • Pipeline finished with Failed
    2 months ago
    Total: 909s
    #177090
  • Status changed to Needs work 2 months ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Added some comments to MR.

  • Status changed to Needs review 2 months ago
  • Pipeline finished with Failed
    2 months ago
    Total: 906s
    #177874
  • Status changed to Needs work about 2 months ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Can be rebased so tests appear green please.
    Also is it meant to be draft?

    For the CR you can actually go ahead and create it just don't check published yet till the issue is merged.

Production build 0.69.0 2024