Closed (won't fix)
Project:
Drupal core
Version:
8.0.x-dev
Component:
javascript
Priority:
Normal
Category:
Feature request
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
6 Sep 2008 at 18:49 UTC
Updated:
14 May 2015 at 12:49 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
stella commentedRe-attaching with patch made from within the drupal directory this time, instead of within the misc directory.
Comment #3
stella commentedThis new JS filterXSS() function is intended for use by JavaScript files in Drupal which handle user input directly. To use it just do:
Cheers,
Stella
Comment #4
robin monks commentedI tested it out:
document.write(Drupal.filterXSS('<script>alert("xss!");'));and this came out:
Looks good, and very useful IMHO.
Robin
Comment #5
lilou commentedThis patch is committed :
#197425: Usability: enable BLOCKQUOTE by default
Comment #6
stella commentedUpdated. Thanks.
Cheers,
Stella
Comment #7
john morahan commentedDoesn't seem to be working properly. I tried this:
document.write(Drupal.filterXSS("<strong> <script>alert('xss');</scr"+"ipt> foo </strong>"));It wrongly removed the
<strong>, and failed to remove the<script>.Comment #8
lilou commentedNeed pass this tests : http://ha.ckers.org/xss.html
Comment #9
stella commentedYup, there was a big error in the last patch but I've fixed that and re-rolled the patch again. I've tested it with John's example above, along with most of the ones from the link that lilou provided.
lilou: thanks for that link, it was very helpful!
Cheers,
Stella
Comment #10
lilou commented@stella : you can test all in one ...
Comment #11
nedjoI can imagine why this might be useful, but it's a fair bit of code and we won't be using it yet in core.
Can you expand a bit on the use cases? Why is this needed? When is checkPlain not appropriate? How widespread is the need? (Without I guess naming specific modules that should be doing this but aren't ;)).
Comment #12
stella commentedI know of a couple of modules (which shall remain nameless) who need this functionality. These modules have javascript which take input from the user (trusted and/or untrusted users), do something with it and then display it. This user-entered input can validly contain html tags, and this is in fact a feature. Therefore using Drupal.checkPlain() is not an option for these modules as it would break the functionality.
Comment #13
stella commentedI've tested all of the various XSS strings in the file lilou provided and as far as I can see all tests passed. I'd appreciate it if someone else could also verify this.
Cheers,
Stella
Comment #14
moshe weitzman commented@stella - these modules (why should they remain nameless?) take untrusted input and show them to different users? I doubt it, because then you could have run filter_xss() on the server side. I don't yet see the point in filtering a user's own input when shown to self?
Comment #15
stella commentedI don't want to name them here because I think they're vulnerable. I've been talking to Heine about this issue, but have only just realised that no mail was sent to the security team list, so I've sent one now.
To answer your question, these modules take untrusted input from node body field and displays it to any users who can view the same node, so it's not just shown to self. See my mail to the security list for more details on how this can happen.
Cheers,
Stella
Comment #16
Anonymous (not verified) commentedThe last submitted patch failed testing.
Comment #17
stella commentedRe-rolled patch against latest HEAD.
Comment #18
markus_petrux commentedhmm... couldn't you do this using an AJAX request where ANY input format could be invoked?
filter_xss() is pretty limited because it allows only whitelisting HTML elements, and then it blindly allows any attributes in them, except on* and style, but you can still pass class or id, which can cause harm to the page layout, or otherwise unexpeted results. So, there maybe someone that needs a different kind of filter such as HTML Purifier, htmlLawed, WYSIWYG Filter, etc.
PS: when porting filter_xss(), please take this issue into account.
Comment #20
lilou commentedfailure was due to HEAD not installing properly
Comment #21
blueyed commentedI think Markus has a valid point here:
why not implement it through an AJAX request and use the same functionality as on the server side?
This would provide the same results without duplicating any code.
Comment #22
wrwrwr commentedNot bad, but it won't be that easy :) Should be simpler and cleaner using AJAX, but if you want it that way, here are some thoughts.
Firstly, it eats my tags:
both give just: uuu</em>. (Seems it only likes first tags: "a<em>b</em>c<em>d</em>" gives "ab</em>c<em>d</em>".)
Secondly, the "for (var character in replace) ..." loop is risky. According to par. 12.2, ECMA-357, order of properties is implementation dependent. Not sure if any implementation would really reorder that, but, if so, this would at least cause removing of Netscape 4.x JS entites ineffective.
Thirdly, entity decoding doesn't seem to take numerical character entities into account, so:
should work in IE6 (that is x0D before or inside a protocol). This is unconfirmed, because it eats my tags ;)
While trying to verify the above I've hit something like this:
which surprisingly does work (IE6, a script in an article using document.write). Not sure why. :)
Comment #23
robloachIs there anywhere in core that would benefit from this?
Comment #24
stella commentedSorry for the delay in responding. I've completely reworked the patch based on markus_petrux's suggestion to use AJAX. It's now much simpler and easier, and since it uses Drupal's existing filter_xss(), it shouldn't have any of the limitations that existed in the previous patch.
It defines a
system/filter-xssmenu callback item, which calls filter_xss() on $_GET['string']. There's a shortDrupal.filterXSS()javascript function which uses a synchronous ajax request to retrieve system/filter-xss. Personally I would prefer an asynchronous ajax request, but I don't see how that is possible.I would also like to extend the patch so it can handle the second param to filter_xss(), which is an array of allowed tags, but haven't decided how best to implement this. So feedback much appreciated.
Cheers,
Stella
Comment #25
markus_petrux commentedBeing a GET request, it may fail depending on the size of the string to parse -vs- server configuration and/or hardcoded limitations.
See for example: http://httpd.apache.org/docs/2.0/mod/core.html#limitrequestline
Depending on the purpose of this API, it might be interesting to use filter_xss_admin() or check_markup(). For passing arguments, maybe using Drupal.settings?
Comment #26
markus_petrux commentedIn regards to synchronous/asynchronous dilema... if it was asynchronous, it could accept a callback which would be used to process the response, which probably be used to alter the DOM in some way, I guess. :)
Comment #27
stella commentedHere's a new patch which uses POST instead of GET, and which has support for the optional "allowed_tags" param to filter_xss().
Within your javascript, you use it like:
or
If we were to use asynchronous, then rather than returning the safe string directly, we would need to alter the DOM and replace the unsafe string, or alter a particular div/span, etc, with the filtered string. This may not suit all use cases.
Cheers,
Stella
Comment #29
stella commentedRe-roll...
Comment #30
sunComment #31
kkaefer commentedWhile using synchronous XMLHttpRequests (the A in AJAX means asynchronous, so this can no longer be named ‘AJAX’) facilitates the implementation of this function, it comes at a high cost: When the server or the user’s connection is slow, such a request COMPLETELY BLOCKS the browser. The user can’t do any action on the site and has to wait until the request finishes.
Comment #32
kkaefer commentedI don't think such a function is really necessary in client-side JavaScript. The reason for filtering text for XSS is that an attacker might foist code to another user, stealing their session or performing other malicious actions like forging requests. However, when the user enters text which is subsequently injected into the very same page, the user could only harm themselves. When the input is stored on the server, it has to be filtered anyway *on the server* before it is sent back to the user (or another user).
Drupal.checkPlain()is mainly used for being able to display literally what the user entered and less for security purposes.Comment #33
ufku commentedSee #586098: Add a core Drupal.checkMarkup() function like check_markup() which could be more useful for input filtering.
Comment #34
sunNo longer possible to do for D7.
Comment #35
stella commentedThe Lightbox2 module had a SA a few months ago that required a Drupal.filterXSS() type function. The result was we implemented the above patch as a lightbox2 function. The asynchronous approach isn't ideal, but we can't use synchronous as that allows malicious code to be executed. Perhaps if we filtered the title or rel attributes for xss code, then this approach wouldn't be needed.
Comment #36
anjalik commentedjs_filter_xss.patch queued for re-testing.
Comment #37
nod_First it needs a reroll,
Second it needs to not use
async: false, just like the checkMarkup issue.Comment #38
stella commentedthat would allow inserted javascript to run on the site before the sanitized version was returned, so where's the point in adding this function then??
Comment #39
nod_Well no, you have to wait for the callback to insert your sanitized content. You can't just use procedural code in JS, it doesn't work that way.
Comment #40
dsnopekI've experimented with implementing this purely in Javascript, without an AJAX call back to Drupal. You can see my code here:
http://jsfiddle.net/dsnopek/ygwyaw18/
It seems to work, but without a TON more review and testing, I can't really say there isn't a browser/configuration/trick to get around it.
Comment #41
nod_With CKEditor we have something similar because of the same security concerns. If we want that it should be looked into. It's using an async ajax call.
Comment #42
nod_The use case outline in #12 is a bit thing to add that sort of functionality especially when the kind of people doing that nowdays are probably using react, angular or whatever is popular in 2 weeks.