Refactor Xss::attributes() to allow filtering of style attribute values

Created on 28 January 2020, almost 5 years ago
Updated 16 May 2024, 6 months ago

Currently, any inline styles in HTML get stripped out when editing content for text-formats that use both the core CKEditor and any output filtering. This includes simple and generally useful styles like <td style="width: 25%">. #2099741: Protect WYSIWYG Editors from XSS Without Destroying User Data β†’ put this filtering in place to prevent XSS attacks via saved content being rendered by an editor. While this brings good safety, the current blanket prohibition on any inline styles while CKEditor with output filtering is used causes issues such as #2785483: [upstream] Cannot set cell width or height because inline styles are stripped β†’ and #3073961: allowed styles are removed upon editing in ckeditor β†’ .

#2099741: Protect WYSIWYG Editors from XSS Without Destroying User Data β†’ and the Text editor XSS filtering documentation β†’ indicate that editors can override the XSS filter class used and provide their own implementation. Unfortunately, extending \Drupal\editor\EditorXssFilter\Standard to add filtering of style attributes requires overriding the large and complex \Drupal\Component\Utility\Xss::attributes() function.

I would like to propose refactoring \Drupal\Component\Utility\Xss::attributes() to make the code more understandable as well as make it easier for child classes to add support for filtering of inline style attributes while continuing to use the default filtering for all other attributes.

I'll follow up with a proof-of-concept refactoring of \Drupal\Component\Utility\Xss::attributes() that maintains existing behavior by default, but is easier to extend for this purpose or related purposes.

✨ Feature request
Status

Needs work

Version

11.0 πŸ”₯

Component
EditorΒ  β†’

Last updated about 7 hours ago

Created by

πŸ‡ΊπŸ‡ΈUnited States adamfranco

Live updates comments and jobs are added and updated live.
  • Needs issue summary update

    Issue summaries save everyone time if they are kept up-to-date. See Update issue summary task instructions.

  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Comments & Activities

Not all content is available!

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

  • πŸ‡³πŸ‡ΏNew Zealand john pitcairn

    @very_random_man re #55: hook_editor_xss_filter_alter() and swapping the class used is only useful if the filtering is happening via a text editor. It's of no help if something else like Views is calling Xss::filter().

  • last update over 1 year ago
    Patch Failed to Apply
  • last update over 1 year ago
    Patch Failed to Apply
  • πŸ‡ΊπŸ‡¦Ukraine eugene.brit Kyiv πŸ‡ΊπŸ‡¦

    The patch from #60 has not applied for D9.5.9
    Re-roll for 9.5.9

  • πŸ‡¦πŸ‡ΊAustralia Nadim Hossain

    #60 missing "datetime", #62 was working fine for me in 9.5.9, so rerolled the same patch for 10.1.x

  • πŸ‡«πŸ‡·France S3b0uN3t Nantes

    The proposed patch now only applies to attributes using single quotes. I'm updating the patch (for 9.5.x) to work for double quotes as well.

  • Open in Jenkins β†’ Open on Drupal.org β†’
    Environment: PHP 8.1 & MySQL 5.7 updated deps
    last update about 1 year ago
    29,836 pass, 16 fail
  • last update about 1 year ago
    29,836 pass, 16 fail
  • πŸ‡ΊπŸ‡ΈUnited States kwfinken Lansing, MI

    This should be moved over to D10 as D9 is approaching EOL and D10 is where such maintenance should reside.

  • πŸ‡΅πŸ‡ͺPeru krystalcode

    I have come across this recently and I tried to organize the reasoning behind the whole issue and come to a conclusion.

    Impact

    First, I think I understand the reasoning of the current behavior, but here is the result - which I think is worse than the intentions.

    Step 1: Security-aware developer puts a filter in the text format, such as HTMLPurifier or HtmLawed, in order to find a balance between allowing some inline styles capabilities but mitigating at least some risks.
    Step 2: Drupal core says, sorry developer, you cannot have a partly secure setup. If you need inline styles, go ahead and remove your security filter so that you have a completely insecure setup.
    Step 3: Client goes "I came to Drupal from X system for being a great CMS, but I cannot do such a basic thing like setting the size of some text and adding some custom padding, Drupal is so limiting me".
    Step 4: Account manager sees the dollars going away, ok developer let's remove the security filter, content editors are trusted users.
    Step 5: Attacker gains access to a content editor's account and engineers an XSS attack, or click-jacking, or whatever pleases, through script tags or style attributes.
    Step 6: Administrator user views or edits that content item and is subjected to the attack.

    Drupal core allows me as a developer/site builder to have a completely insecure text editing configuration, if that's what I deem appropriate for my use case. But it prevents me from having a reasonably secure setup.

    Proposed solutions

    First, the idea is that the content is stored "as is" in the database and the filtering happens during rendering. This is intentional because if something would be filtered before saving it into the database, that's gone forever leading to errors. This is exactly what happens though with this issue and it is inconsistent with this design.

    What are the disadvantages of delegating the rendering to the text editor? CKEditor has its own system for this, being Advanced Content Filtering in v4 or General HTML Support in v5. Provide the default configuration for what is provided by Drupal core i.e. CKEditor + the default text formats, and let developer configure the text editor as needed if they customize their setup.

    Alternatively, would it make sense to load the same security filters that are configured for the frontend rendering - which I believe are determined by the FilterInterface::TYPE_HTML_RESTRICTOR constant, load them in the text editing rendering i.e. in the Standard editor XSS filter?

    This way I get the same result in both frontend and text editing rendering. It does violate though the design of not overriding the original data. Could be offered though as an option to the developer to decide.

    Keeping the HTML code safe is a massive subject, and that's why there exist specialized libraries for it. Trying to reinvent this within Drupal core (referring to allowing simple properties only within inline styles), will only deliver a mediocre solution, locking developers into it - unless you get into complex efforts to override/extend/replace classes, increase code maintenance for core and contrib/custom modules. Better let developers use the tools that specialize in solving these issues.

    I have just reviewed this this week and I am fairly unfamiliar with components involved, so if I'm misunderstanding this part of the stack please do correct me.

    Documentation/help

    Lastly, after a solution is decided, I think what is really missing is guidance for the developer/site builder. I think that the majority of developers/site builders would not be familiar with all these details, the security risks, what alternative solutions to provide to text editors. So let's create a documentation page with advice like the ones @Wim Leers suggested, plus an explanation of this issue i.e. the frontend/text editing rendering and how to properly configure both the text editor and the text filters, and link to that documentation in the text format create/edit pages.

  • πŸ‡³πŸ‡ΏNew Zealand john pitcairn

    Re #66: yes, but this issue does not just affect text formats/editors.

    It also affects things like views rewrites, where you might want to rewrite and add a style attribute that is benign - passing a css property value through to a stylesheet for example. No text editor is involved there.

  • last update 12 months ago
    29,448 pass, 7 fail
  • πŸ‡«πŸ‡·France Quentin.Le-Delas

    I have update the #64 patch for the last core update 10.2.3

  • last update 10 months ago
    Patch Failed to Apply
  • πŸ‡«πŸ‡·France Quentin.Le-Delas

    update patch with LF format

  • πŸ‡«πŸ‡·France Quentin.Le-Delas

    the final patch rename correctly.

  • last update 10 months ago
    Patch Failed to Apply
  • Status changed to Needs review 9 months ago
  • πŸ‡ΊπŸ‡ΈUnited States DamienMcKenna NH, USA

    This is a reroll of #64/#71 for 10.2.x.

  • Status changed to Needs work 9 months ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Recommend using MRs

    Feature will need test coverage

    Issue summary should use standard template for reviews and committers

  • πŸ‡ΊπŸ‡ΈUnited States paramnida

    Re-rolling #43/68 for 10.2.3

Production build 0.71.5 2024