TL;DR
We need a distinct "XSS Filtering For Editors" mechanism to prevent assistive editors like CKEditor from becoming an XSS attack vector. We also need a mechanism for specific assistive editing implementations (say, a Geshi code syntax highlighter for fields that store CSS) to override this step if they need special behavior.
The Details
- Currently, we filter all content on output. That allows us to protect site visitors from XSS attacks while preserving content in its "raw" form. In addition, it allows us to enforce markup standards ("No bold tags! No divs!") and apply transformations ("Curly quotes! Replace tokens with rich data!")
- When a user edits content-with-an-input-format, we send the raw content to them for display in a form. This isn't a problem, because browsers don't actually parse markup that's inside of an edit box.
- HOWEVER, because some assistive editors (CKEditor included) actually parse and display the raw content, XSS exploits in the raw markup can be triggered by the editor itself. (CKEditor can prevent simple 'paste a script and it gets executed' scenarios using its ACF framework, but if unsafe data actually gets saved to the DB, then a privileged user opens an edit window and changes its format to one with an Assistive Editor, the unsafe raw content could be executed.)
- We can't simply apply the normal output filtering before sending the content to the editor; that would also trigger the markup enforcement and transformational filters that shouldn't affect the editing process.
- We also can't simply run the current XSS filter function on raw content before sending it to the editor. Our current XSS Filtering mechanism uses a whitelist of tags, stripping out markup that should actually be preserved for editing purposes, applies a blacklist of attributes to any remaining tags, and applies a whitelist of URI protocols to any remaining attributes. This is fine for output, since 'Allowed Tags' lists can be set up for output, but it's is more restrictive than we need to protect the assistive editor from XSS attacks, and will interfere with many valid and safe use cases (like using an <iframe> tag, or using inline CSS styles on an element).
The Solution
Fortunately, extended dialogue at the sprint in Prague has revealed what looks like a good solution:
- Rather than relying on the current input filter system, we will define a new XSS-Protection-For-Editors mechanism that only attempts to scrub XSS attack vectors. It should blacklist a small set of 'inherently unsafe' tags like <SCRIPT>, blacklist attributes that are known XSS vectors like onClick and style, and whitelist known-to-be-safe URI protocols in attributes.
- This XSS-Protection-For-Editors scrubbing operation will be applied before content is sent from the server to the client, whenever an assistive editor like CKEditor is part of the active input format. "Dumb" unassisted text fields would remain unscrubbed, because they're not at risk.
- Because some assistive editors take their own responsibility for certain steps in that scrubbing process, this XSS-Protection-For-Editors operation would need to be overridable by individual assistive editors. For example, the depending on its configuration, CKEditor may want to allow a whitelist of certain inline style attributes through. A code syntax highlighter would qualify as an assistive editor, but would always want the full raw content, and would be performing highlighting operations rather than parsing the content and displaying the actual HTML.
- In those situations, CKEditor's Drupal integration would provide a scrubber plugin that inherits core's XSS-Protection-For-Editors plugin and overrides just the 'inline styles' handling. A hypothetical Syntax Highlighter assistive editor would override all of the steps to let everything pass through.
The Impact
If we implement the plan, where does that leave us?
- Raw text fields using an input format without an assistive editor would remain unchanged. They're raw. They're dumb. If you want to paste in crazy stuff and know it'll never be touched, this is the way to go.
- Fields using an input format with an assistive editor configured would always have the XSS-Protection-For-Editors scrubbing operation performed before content is sent to the client for editing. This would keep assistive editors save from XSS exploits.
- Assistive Editors that can safely sidestep some of those protections (like a syntax highlighter that doesn't actually allow the raw markup to be parsed during editing) can subclass and override the XSS-Protection-For-Editors plugin.
- Because the mechanism for sidestepping the XSS-Protection-For-Editors step is an explicit class, it would be easy for the security team to scan for any modules implementing it and subject them to extra scrutiny.
- End result: minimum impact on user content, maximum protection from XSS when using an assistive editor, and flexibility to override for assistive editors that realllllly need raw access to certain potentially dangerous bits.
There is one situation where content entered by a user could be "scrubbed out" accidentally. If they save XSS-ish data (say, a <SCRIPT> tag) using an input format that doesn't have an assistive editor, reopen the content, change the input format to on that does have an assistive editor, then save, the markup that's removed by the XSS-Protection-For-Editors scrubber would be lost permanently. I think this is acceptable: if you need to paste <SCRIPT> tags and jam onClick() events into your <A> tags, don't use an assistive editor, or use one that's explicitly designed for editing code and uses the override mechanism described in step 3 of 'The Impact.'
The Patch
During the Prague Sprint, WimLeers and members of the CKEditor team produced working proof of concept code for this approach. The patch will be coming shortly.
Comment | File | Size | Author |
---|---|---|---|
#49 | interdiff.txt | 3.57 KB | Wim Leers |
#49 | interdiff-move_filter_types_to_filterinterface.txt | 27.23 KB | Wim Leers |
#49 | editor_xss_protection-2099741-49.patch | 111.77 KB | Wim Leers |
Comments
Comment #1
eaton CreditAttribution: eaton commentedComment #2
nod_and of course, tag.
Comment #3
webchickTagging.
Comment #4
Wim LeersThank you so much for that very clear, concise-as-possible writeup, eaton! :)
Also special thanks to mr.baileys from the Drupal security team, who we disturbed numerous times on that day to ask for his guidance :)
I want to highlight a few important aspects of this patch:
\Drupal\Component\Utility\Xss::filter()
now has a new, optional$whitelist = TRUE
parameter (API addition, not change!).\Drupal\Component\Utility\Xss
, all existing test coverage is leveraged while solving this issue; only a few additional test cases had to be added. So no only do we prevent code bloat/duplication, we also guarantee this at least as secure as our existing XSS protection.\Drupal\editor\EditorXssFilterInterface
:filterXss()
method, period. No need to create yet another plugin type, plugin manager and yet another thing in the DIC for that.If I'm wrong, and there are good reasons to use the plugin system, I of course won't mind to make the necessary changes.
XssTest
(unit test), run like this:cd core; php vendor/bin/phpunit tests/Drupal/Tests/Component/Utility/XssTest; cd ..
StandardTest
(unit test), run like this;cd core; php vendor/bin/phpunit modules/editor/lib/Drupal/editor/Tests/editor/EditorXssFilter/StandardTest; cd ..
— this has very minimal test coverage only, since this class just reuses theXss
class, which has extensive test coverage inXssTest
.EditorSecurityTest
(integration test). Tests a total of 22 scenarios to ensure all cases are covered.FILTER_TYPE_HTML_RESTRICTOR
). I've also made the documentation of that filter type more explicit: it now specifically mentions XSS prevention as a requirement for a filter to be classified like this.FilterHtmlImageSecure
filter was classified asFILTER_TYPE_HTML_RESTRICTOR
. Probably because it wasn't very clear where it should fit in. By making the requirements to be categorized as that type more explicit ("must prevent XSS"), it's now also clear that the current type for this filter is wrong. I've changed it toFILTER_TYPE_TRANSFORM_IRREVERSIBLE
: the stripping of the original image and replacing it with an "error placeholder image" is irreversible.FilterHtmlCorrector
was also classified asFILTER_TYPE_HTML_RESTRICTOR
, but it doesn't really apply security fixes; it merely tries to improve the HTML. I've reclassified it asFILTER_TYPE_TRANSFORM_IRREVERSIBLE
as well, because once incorrect HTML is fixed, it's impossible to know how to go back to the previous string representation.(It was originally marked as a security filter because there's no harm in running it; it only causes less things to break due to broken HTML. However, considering that this breaks the ability to cleanly reason about filter types, I feel this is better.)
FilterHtml
(whitelist some tags),FilterHtmlEscape
(blacklist all tags),FilterNull
(disallow all content) are the remaining ones that are marked as being of theFILTER_TYPE_HTML_RESTRICTOR
type, and all of them are very clearly correct.Comment #6
Wim LeersLooks like that's only a syntax error on PHP 5.3, which is why I didn't run into it.
Comment #7
eaton CreditAttribution: eaton commentedI may have missed something, but:
Just to be clear on the reasons for this: if you've created a 'raw' input format that doesn't do any XSS prevention on output, the system won't apply any XSS prevention in the editor. Is that correct?
Comment #9
Wim LeersYes, that is correct.
If we wouldn't do it this way, then it would be impossible to use
style="color:pink"
, or<script>
tags in Drupal 8's default Full HTML text format.Reroll to make all tests pass now that an additional bit of metadata is being passed through
drupalSettings
, which is why the tests were failing.Comment #10
Wim LeersFixed two non-security bugs:
The patches above track if you made any changes. If you did not make any changes, and then switch formats, it will not use the XSS-filtered result, but the original value in the DB, and then — if necessary — apply the XSS filtering to switch to your desired format. The rationale behind this is that when switching to a text format without text editor before making changes, you still have the original content as it lives in the DB, without the text editor XSS filtering. I did this so that this relatively common use case is completely unaffected by this patch. (See the
data-editor-value-is-changed
attribute handling ineditor.js
.)The problem he found was when you start with a format without a text editor (e.g. Restricted HTML), type some changes, then switch to a format with a text editor (e.g. Basic HTML), then switch back to the first format without making changes, now your original changes will have been undone, because there was no change tracking yet when you don't have a text editor. That's fixed now.
editor.js
did not yet properly handle this.Comment #11
Wim Leers… and here's the patch for #10.
Comment #12
mr.baileysOnly a quick review, I'll need some more time for a full review :)
Technically, the assistive editor will parse this string prior to display, so what is presented to the end user can differ from this HTML string?
editor_filter_xss() is always called prior to rendering the text editor, not just when switching between formats, so this description is misleading.
Content replaced with "false"
At some point while playing around with the editor, my content got replaced with
'<p>false</p>'
.xssFilteredValue can == json False, in which case the content gets overwritten with
<p>false</p>
Steps to reproduce:
Comment #13
Wim Leers#12: Thanks! I updated the two comments you rightfully found misleading. The "false" problem was fixed in the patch in #11 already, you were probably already reviewing the patch by then :)
Comment #14
mr.baileys$allowed_html no longer makes sense as an argument/variable name since behavior now depends on the value of $whitelist, and could actually contain disallowed tags. Maybe rename $allowed_html (multiple occurences) to just $html_tags?
The same goes for $allowed_tags used elsewhere.
Sorry for the piecemeal review, I'll try and do a more thorough job soon.
Comment #15
mr.baileysI have spent quite some time trying to sneak an exploit past the filtering, but was unable to do so, which means the patch seems to do a good job!
Some smaller, mostly cosmetic issues (together with the comments from #14):
Should be marked as "(optional)".
Should be marked as "(optional)".
Should this also mention that the class should implement EditorXssFilterInterface?
"Also for context." needs to be a proper sentence, or can be removed altogether?
Type hinting for $format & $original_format should be FilterFormatInterface rather than FilterFormat (a couple of occurences throughout the patch).
(See https://drupal.org/node/608152#hinting)
Should start with a third-person verb.
Should be marked as (optional)
Same comment about type hinting, I think FilterFormat should be FilterFormatInterface.
Is "keyup.editor" necessary here, since we are already acting on "change.editor"?
This is actually triggering a PHP Fatal error rather than throwing a NotFoundHttpException:
PHP Fatal error: Class 'Drupal\\editor\\NotFoundHttpException' not found
Was this line removed intentionally? It seems unrelated to this patch.
Comment #16
Wim LeersRemoving "needs security review" because #15 indicates no flaws were found. I still welcome others to try to find holes though :)
#14 & #15: Thanks! :) All fixed, with a few comment replies here:
D'oh, of course — my bad, sorry! Too much copy/pasting. Very glad you caught this.
Yes, because the "change" event doesn't fire right away. In any case, it doesn't hurt.
I improved it slightly now though: as soon as one change/keyup event happened, we stop listening for changes, because we know enough then: we just need to know whether the contents were changed at all or not.
You're right that it's unrelated, but since I had to update the docs there anyway, I noticed this mistake and it's better to just correct it here.
What's still needed to get this to RTBC?
Comment #17
webchickI was referred to this issue by a tap-dancing ladybug man. :)
In seriousness, you may want to reach out to David Rothstein. He's done detailed review of filter system patches in the past.
Comment #18
dawehnerThis is a classical drive-by review, so don't expect much.
Additional I noted some @file Definition at least in one place.
This docs disagree with the actual signature of the function.
There is another issue which gets rid of this ugly hack by just using an anonymous function which passes along the html tags
We have a code style which uses "elseif"
I have no idea bout this but this feels like an optimization which limits some possibilities for contrib. Are data attributes meant to be namespaced and so not used in other modules?
Afaik we use @var bool
The ControllerBase class provides an entity manager usable here.
YEAH!
+1!
Comment #19
Wim Leers#17: I pinged David Rothstein using his d.o contact form :)
#18: thanks — drive-by reviews are actually helpful at this stage, and I'm glad to see there's apparently little left to nitpick :)
else if
…data-
attributes are meant to be namespaced, to prevent clashes. Other modules can still use these attributes without problems, of course.Comment #20
David_Rothstein CreditAttribution: David_Rothstein commentedThanks for pinging me. I'm probably not going to get to a full review right now, but I tried to look it over mostly at a high level.
I was under the impression that blacklisting the script tag is not sufficient to stop XSS attacks? (And in general, blacklisting is fraught with peril...) Some background:
- #275811-45: Warn about potentially insecure filter configurations as well as earlier comments
- https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
The latter is the basis for some of the tests in \Drupal\Tests\Component\Utility\XssTest.... Would a blacklist filter that only blacklists
<script>
pass those tests?Since a filter with type FILTER_TYPE_HTML_RESTRICTOR can still be configured insecurely (even intentionally so) the text editor XSS filtering may still sometimes run when it doesn't need to... I'm not sure if that's just a minor inconvenience or a problem.
Double "HTML".
Something is not right towards the bottom there...
Comment #21
Wim Leers#20:
(Trying to formulate a solid response, but I've been out of this for 2 weeks now, so I might be missing something.)
<script>
tag is inherently dangerous in and of itself, because it allows one to execute arbitrary logic. Other tags, like<iframe>
, are only dangerous when they have malicious attributes. Of course, in the heat of that very, very long discussion,<script>
was the only one we could collectively think of. It seems like<style>
is another one we should forbid. Which other tags do you think we should blacklist because they're inherently dangerous.P.S.: we did look at those links, and http://html5sec.org/ too. If you look at the attacks, almost all of them are about tag malformation or malicious attribute values. That's why we concluded that preventing those kinds of attacks in combination with blocking inherently malicious tags must be sufficient.
Comment #22
Wim LeersThis is a very, very important issue to get in Drupal 8. In fact, I think this issue may need to be marked critical.
It'd be great if we could get more insightful reviews, so that we can steadily move towards RTBC.
Comment #23
nod_Too bad it doesn't make the system unstable, it's just critical because of 2 things :p
Comment #24
effulgentsia CreditAttribution: effulgentsia commentedJust a straight reroll for HEAD drift; no real changes.
Comment #25
jibran24: editor_xss_protection-2099741-24.patch queued for re-testing.
Comment #27
Wim LeersStraight reroll.
Comment #28
Wim LeersThis is a critical security feature. I think this being marked a beta blocker is justified.
Comment #29
larowlanMinor: Shouldn't class properties use camel case?
nitpick: coding standards dictate breaking these into multi-lines.
Having read this in detail, all I can muster are coding standards nitpicks.
I don't think those should block this getting in though.
Comment #30
dstolComment #31
Gábor HojtsyArchitecturally this change looks good to me. Based on the issue summary I don't have better ideas to approach this problem either. I think if we can make the API as evident as possible and windows for failure (such as the remote XSS filtering call) not be a problem, then we should be fine. See more comments below.
I needed to read this several times to understand. The $whitelist argument sounds misleading because its not at all a whitelist itself. It specifies if the other argument is a whitelist or blacklist. Maybe if you we name it $operation with allowed values FILTER_ALLOWED, FILTER_DISALLOWED or something like that (defined constants). Or something along those lines would be cleaner. Same later on.
This looks to be a strange pattern that you use an alter to alter a string. Other similar places I think use a regular hook to get the value and then take the last value. I don't have a strong preference, but it looks pretty strange to have an alter hook for a string only :D)
Nice way to document how the filter should interface :) Great :) ++
Is this not also happening in an error condition? Ie. let's make sure that the server being inaccessible or something along those lines will not cause an issue. I suspect that is already ok with the strict checking for false, but wanted to make sure I ask :) Sounds like the remote connection may play a role in how the XSS protection is performed. Also is this call blocking (ie. no window for the XSS while this is running)?
This switch from the route param being the same as the variable name but then not being the same thing is interesting... I think we want to rename the route parameter to include '_id' as well so its clearly not a whole loaded format?
Qualify what XSS is maybe here, since this is the top level place where this is documented. I mean "XSS (Cross-site scripting)"
Minor: dot :)
Limiting disallowed tags sounds like double negation to me?! Not clear what do you meant here? Tests specifying disallowed tags?
Also something is missing from the docs here?!
Comment #32
nod_Ok not even the right issue. nevermind me. I need coffee.
Comment #33
nod_Comment #34
nod_In
filterXssWhenSwitching
I'd send extra arguments to the callbackSo you can do
filterXssWhenSwitching(field, format, originalFormatID, Drupal.editorAttach)
might as well optimize for that, it's still possible to not make use of the parameters.A possible issue when creating a new node, if you're using the restricted HTML format (no CKEditor) and write a
tag, when switching to CK it will be removed, but switching back to restricted HTML, the script tag is still removed. Works as expected on a saved node. That's not true, it's like the current formUpdated, says it's changed when it might not be. Usingkeypress
would be better, at least it won't pick up dead keys. Ideally we'd be comparing values but good enough for now I guess. Apart from that JS looks good to me :)Comment #35
Wim LeersStraight reroll of #27. Next: reroll that addresses all feedback since.
Comment #36
Wim Leers#29:
Action
,FieldFormatter
,FieldType
,FieldWidget
etc. annotation classes also don't do this. So if we want to change that, then we should do that in a follow-up. Particularly because there already is a class property that uses an underscore in\Drupal\editor\Annotation\Editor
, so only using camelCase for this new class property would be inconsistent.#31:
error
callback (with the sole exception of Edit module). It is possible to also implement it here, but it'll complicate the rest of the code as well. Therefor I'd like to do that later, which won't put us in a worse situation than we're already in.This call is indeed blocking: the new Text Editor is only attached after the server-side XSS filtering has occurred successfully. Since it's precisely the "XSS due to a Text Editor being loaded" problem that we are solving, the answer is: "No, there is no window for the XSS while waiting for the response to this request."
#34:
callback(field, format)
, to get rid of one intermediate function call, always: good catch! Done.<textarea>
, then switching to CKE and back: there's no way around that. #2166399: Changing CKEditor configurations by changing text formats causes markup to be lost: warn the user when performing this advanced action exists to warn/inform the user appropriately when that happens. See the last paragraph of the "The impact" section of eaton's issue summary.keypress
. Second: note that this is only used in the "there is no text editor" case; if there is a text editor, then that text editor'sonChange
method will be used, which prevents the problem you describe!Now, with all the nitpicks and small optimizations out of the way, let's get a +1 from the security team and then let's get this in!
Comment #37
Wim Leers#2166399: Changing CKEditor configurations by changing text formats causes markup to be lost: warn the user when performing this advanced action broke this patch. Rerolled.
Comment #38
nod_This is a reroll because the indentation standard changed for JavaScript files. No need for commit credit because of this reroll.
Comment #40
Wim Leers38: core-editor-xss-protection-2099741-38.patch queued for re-testing.
Comment #41
Wim LeersThe #38 reroll moved some files around in the patch for no reason, hence breaking tests. It also introduced unrelated whitespace changes. Please don't do that. If you do, at least provide an interdiff.
This is a straight reroll from #37.
Comment #42
nod_Sorry for the sloppy reroll.
Comment #44
dstolWim Leers brought this to the attention of the security team and asked that we give it a review. This feature seems like a great solution to mitigate what seems like a potential vulnerability in D8.
The security team had a similiar discussion about modifying input filters allowed/disallowed attributes as it relates to https://drupal.org/node/2081887. I’m glad to see mature and well thought out solution presented solution for D8.
The only tag that’s being explicitly blocked is
in Drupal\editor\EditorXssFilter? Style should be added to that list, #20 hits this too. See https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#STYLE_tags_with_broken_up_JavaScript_for_XSS and the several subsequent exploits. Link as well via a remote style sheet attack. See https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Remote_style_sheet. I’d like to see style and link blacklisted and tests added for them.Comment #45
Wim LeersBlacklist more tags
While working on this patch to address #44, I decided to implemented as comprehensive test coverage as possible: I expanded
\Drupal\editor\Tests\editor\EditorXssFilter\StandardTest
with the entire list of known XSS attack vectors at https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet — this test has now grown from 4 to 189 tests! (This is also why the patch has grown >40 KiB in size.)In doing so, I discovered two more problematic cases:
<embed>
and<object>
are safe most of the time… unless you have Flash installed. Flash may contain JavaScript code itself, which would have access to the main document… and hence opening the door for all sorts of maliciousness.Discussed this at depth with dstol on chat and with the CKEditor CTO, they both agree with these additions.
This does imply that it will be effectively impossible to use the
<embed>
and<object>
tags directly whenever you use the Basic HTML format, even when you've configured it to allow the<object>
and<embed>
… you'll only be able to use them in text formats without anyFILTER_TYPE_HTML_RESTRICTOR
filter, such as the Full HTML format.In other words: end users may experience data loss!
Being smarter to prevent data loss
Of course, data loss is not acceptable. That's why I talked to both dstol and the CKEditor CTO about working around that problem. We've come up with a solution that works:
<script>
,<style>
,link
,<embed>
, and<object>
.That's it in a nutshell. Please see
\Drupal\editor\EditorXssFilter\Standard
for details.In this reroll
The test coverage was expanded to ensure that this works correctly: switching to/from a text format with HTML restrictions but with the
<embed>
tag allowed was added to the tests.No further API additions/changes were necessary:
EditorXssFilterInterface
already foresaw the possibility of text editor XSS filters needing to access the metadata of the involved text formats to do its filtering, now the default text editor XSS filter just leverages that.For the unit tests to work without mocking procedural code, I had to move some procedural functions in
filter.module
ontoFilterFormatInterface
though, but that needed to happen anyway. That's being done in #2184315: Move filter_get_filter_types_by_format() and filter_get_html_restrictions_by_format() onto FilterFormatInterface; this issue is now effectively blocked on that.Comment #46
Wim Leers#2184315: Move filter_get_filter_types_by_format() and filter_get_html_restrictions_by_format() onto FilterFormatInterface got committed, yay! This is now unblocked :) Go, testbot, go!
Comment #48
dstolComment #49
Wim Leers#2184315: Move filter_get_filter_types_by_format() and filter_get_html_restrictions_by_format() onto FilterFormatInterface was opened to keep this patch focused on the scope of this issue: unrelated refactoring done in another issue.
But… sadly, #45 came back red, because PHPUnit failed on qa.d.o, yet passed with zero complaints (let alone failures) locally. It failed for legitimate reasons.
The fix is simple, but like #2184315, it requires a bit of refactoring, to avoid the same "mocking procedural stuff in PHPUnit tests" problem. In theory I should open a new issue for it. But I think it's easier/faster for everybody, including core committers, to just do it here. It's moving the
FILTER_TYPE_<something>
constants fromfilter.module
toFilterInterface
. It's an easy search/replace operation, and there's extensive test coverage.See interdiff-move_filter_types_to_filterinterface.txt.
So, attached is a reroll that fixes the one bug in #45, along with some super simple refactoring to allow for clean, green unit tests.
Comment #50
dstolThis has been quite an epic battle to get this right. It's ready now.
Comment #51
Wim LeersAlmost forgot!
Please give commit credit to these folks:
Wim Leers, wwalc, mr.baileys, eaton, dstol
. Thanks!Comment #52
webchicksun indicated he'd like to take a look at this, so assigning to him.
Comment #53
webchicksun eyeballed this the other day and the only comment he had was that it'd be nice if there was a docblock topic or similar to explain this new API, which included some of the overview info that's available in the issue summary, but not in the code. He also said though that he didn't feel this was a commit-blocker, and could be done as a follow-up.
Comment #54
Dries CreditAttribution: Dries commentedThe patch looks great. It's surprising that this is not part of the WYSIWYG editor itself, and that many content management systems needs to implement this. Any more color on that?
Comment #55
eaton CreditAttribution: eaton commentedCKEditor does implement scrubbing functionality for content coming into the editor via user input. The challenge comes when it also must deal with text from the CMS that didn't come in via the assistive editor's sanitization code.
We're facing it due to the flexibility of Drupal's input format system: the level of variation we allow, and the potential for a piece of content to switch formats over its lifespan, means we expose this subtle edge case and must handle it.
Comment #56
effulgentsia CreditAttribution: effulgentsia commentedTo clarify #54, the issue summary says:
Why does CKEditor consider that to be acceptable?
Comment #57
effulgentsia CreditAttribution: effulgentsia commented#56 was xpost with #55, so trying to rephrase the q:
http://ckeditor.com/blog/CKEditor-4.1-RC-Released says that the ACF is not security related. ACF in general makes sense to apply on user input only, and not on CMS-supplied text, but shouldn't CKEditor also have a security feature that is applied across the board? Maybe it shouldn't, but if that's the case, I think Dries wants to understand why that is.
Comment #58
sunre: @Dries / @effulgentsia:
The way I see it, one of the primary reasons for why we're doing it in Drupal is that the Editor module in core is not restricted to CKEditor. If a different client-side editor library is used, then Drupal should still be secure.
We can't expect every editor plugin implementation to figure out this fundamental security aspect on their own. And as @eaton already mentioned, the concept of multiple text formats as well as being able to switch between them is custom to Drupal.
Comment #59
webchickOk, seems like there is general agreement that this is a good idea.
I'll be perfectly honest and say that most of this is way over my head. But it's also a beta blocker that has been sitting at RTBC for more than a week at this point, which doesn't feel good. I also did read the entire patch, and it's well documented and easy to follow. So in case we do introduce a regression here, seems like it'd be pretty easy to clean-up. I'll also be seeing Wim in person next week so I can give him a noogie in person if so. ;P
The one main concern I had with this patch was about the blacklist for tags like embed and object, since there are definitely valid reasons to enable those tags for users, and ways to safeguard them from being wide-open security holes. (Embed filter module, for example) However, the logic in filterXss() allows for this, by cross-referencing the blacklist against the explicitly allowed tags.
Lots of very nice test coverage as well, which is great. So I think this is good to go.
Committed and pushed to 8.x. Thanks!
Comment #60
webchickBtw, that wasn't me being aggro, that was #2191619: New on-page comment form is deleting all hidden files :( :(
Comment #61
sunThanks!
Created #2191873: Document the WYSIWYG XSS filtering concept and architecture for developers to add some bird-level documentation on the architectural security concept, which was my only concern, as @webchick paraphrased already.
Comment #62
dawehner:( #2193023: EditorXssFilter/StandardTest::dataset #25 fails on php 5.4
Comment #63
Wim LeersI've updated https://drupal.org/node/1817474 because the
FILTER_TYPE_*
constants were moved toFilterInterface
in this patch.I'll get #2191873: Document the WYSIWYG XSS filtering concept and architecture for developers done.
Comment #65
chx CreditAttribution: chx commentedI filed #2364647: [sechole] Remove blacklist mode from Filter:XSS