How secure is client-side HTML sanitization?
I've been looking at Pagedown.js lately in hopes of using mark-down on pages instead of ugly read-only textareas.
I'm very cautious as it seems easy to trick a converted converter. I've seen some discussions about Angular.js and its html bindings, and heard a bit about html bindings being previously unsafe when Knockout.js 3.0 was released.
Seems like all one needs to do to disable sanitizers in Pagedown.js like -
var safeConverter = new Markdown.Converter();
// safeConverter is open to script injection
safeConverter = Markdown.getSanitizingConverter();
// safeConverter is now safe
// Override the getSanitizingConverter pseudo-code
Markdown.getSanitizingConverter = function () {
return Markdown.Converter;
};
They can open a site for script injection. isn't that true
edit
So why would such a library package a sanitizer to use the client? Of course they say don't render unsanitized html, but the next line says to use Markdown.Sanitizer.
How does Angular not use the sanitizer service, or is it farce?
I believe there is some misunderstanding of the purpose and nature of this "sanitizer".
The purpose of a cleaner (eg Angular's ngSanitize
) is not to prevent "bad" data from being sent to the server side. Instead, here's another way: there's a sanitizer out there to protect non-malicious users from malicious data (due to security holes on the server side (yes, no setup is perfect) or obtained from other sources) (those beyond your control)).
Of course, as a client function, the sanitizer can be bypassed, but (since there are sanitizers that protect the user (not the server)), bypassing it just leaves the bypasser unprotected (you can't do anything about it) , you shouldn't care either - it's their choice).
Additionally, sanitizers can play another (possibly more important) role: sanitizers are tools that help developers better organize their code, making it easier to test certain types of vulnerabilities (such as XSS attacks), Even help with actual code reviews for such security holes.
In my opinion, the Angular documentation summarizes the concept pretty well:
Strict Context Escape (SCE) is a pattern in which AngularJS requires binding in some context to produce a value that is marked as safe to use in that context.
[...]
SCE assists in writing code by: (a) being secure by default, and (b) enabling auditing for security vulnerabilities such as XSS, clickjacking, etc.becomes much easier .[…]
In a more realistic example, one could render user comments, blog posts, etc. via bindings. (HTML is just one example of a context where rendering user-controlled input creates a security hole.)For HTML, you can use a library on the client or server side to sanitize unsafe HTML before binding to the value and rendering it in the document.
How do you ensure that every place you use these types of bindings is bound to a value that has been sanitized by the library (or returned to a value that is safe to render to the server)? How do you make sure you don't accidentally delete the sanitized value on that row, or rename some property/field and forget to update the binding to the sanitized value?
To be on the safe side , by default you want to ensure that any such binding is disallowed, unless you can be sure that it is safe to bind with a value in that context . You can then audit your code (just do a simple grep) to make sure you only do this for those safe values that you can easily tell - because those are received from the server, cleaned up by the library Wait. You can organize your own codebase to help with this - perhaps only allowing files in a specific directory to do so. Make sure that the internal API exposed by this code doesn't mark arbitrary values as safe, making it more manageable .
Note 1: The emphasis is mine.
Note 2: Sorry for the long quote, but I think this is a very important (albeit sensitive) thing and is often misunderstood.