0

I want my expresJS server to detect and stop any request containing XSS input before it gets saved in the database, as my website does not utilize any html input, and it does not need to.

What is the best method for doing that?

2
  • How do you determine what XSS input is? Do you mean HTML?
    – schroeder
    Commented Mar 9 at 10:57
  • 1
    If your web site does not utilize HTML then anything which gets read out of the database should not be interpreted as HTML which means it does not matter if there is some XSS stored inside since it gets never activated. This is like preventing SQL injection on an input if the input gets never used inside an SQL statement. Commented Mar 9 at 11:58

1 Answer 1

3

Cross-site scripting is an output problem, not an input problem. It happens when data is not correctly escaped before using it in an HTML context, or when non-HTML data (e.g., plaintext) is misinterpreted as HTML markup.

Trying to filter or reject HTML markup at the input level is a very poor approach for several reasons. First, it will never be perfect, because there are no clear boundaries between text input, harmless HTML markup and XSS attack vectors. If you aggressively reject anything that vaguely resembles HTML markup (e.g., all text with angled brackets), you will likely cause problems for your users. Anybody who just used angled brackets in their text but didn't mean to post HTML markup will trigger the filter and be unable to proceed. The same is true for users who did post HTML markup but for perfectly legitimate reasons (e.g., to discuss it or save it just for themselves). If you try to distinguish between those harmless cases and malicious HTML markup, you will likely miss actual attacks, because HTML is complex, and there are all kinds of weird parsing rules and browser quirks. This is why input filters can create a false sense of security.

A much better approach is to treat this as an output problem. Whenever you output data that might be interpreted as HTML markup, use HTML-escaping (i.e., convert all special characters like angled brackets into HTML entities). If you absolutely do not want to output data as HTML markup, make this explicit: Set the Content-Type header of the response to an appropriate media type (e.g., text/plain), and maybe also use the file extension to indicate this is not HTML (e.g., use .txt).

Features like Content Security Policy (CSP) can also be useful if the database output is displayed by browsers and might contain HTML markup. This allows you to, for example, completely disable all inline JavaScript. Note, however, that CSP is just a second line of defense.

3
  • 1
    Excellent answer (+1). OP, in addition to the steps mentioned above, when writing data to a DOM element, always write the data to the element's .innerText property, not the element's .innerHTML property. This way the data will be rendered as plaintext, even if it contains HTML markup.
    – mti2935
    Commented Mar 9 at 13:50
  • Thank you for your useful comment, but I got my inspiration from Cloudflare as they block any request containing XSS before it reaches the server and thought it was a good idea 😅. I will definitely use your comment to upgrade my website security. thank you again
    – a_duck
    Commented Mar 10 at 6:33
  • What Cloudflare offers is a Web Application Firewall (WAF). WAFs are, at best, an additional security measure, because they suffer from the exact same problems mentioned in the answer: They can only detect some attacks based on known patterns, and it's difficult to find the balance between filtering too aggressively and being too permissive. I would focus on the measures from the answer. When that's done, maybe add a WAF (don't implement it yourself), but I wouldn't expect too much from it.
    – Ja1024
    Commented Mar 10 at 10:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .