In NodeJS, what is a good way of ensuring user submitted data in (text input) forms is not malicious?

Stripping out HTML tags is not a sufficient approach to protecting yourself from XSS. Consider the following input:

<scri<script>pt>

If you strip out the <script> tag, another script tag is created. This is just one example - there are many other attacks that could be used.

You should look into protecting yourself from XSS on the server side - this way users do not have the ability to modify/bypass your client side code.

Protecting yourself against XSS is totally doable, but you should make sure you are using the correct approach. As usual OWASP's instructions on how to protect yourself is probably the best way to go.


There are two main methods that are commonly discussed when dealing with user input. These two methods are validation and sanitisation.

Both of these should be most definitely done on the server side. Client side protections will not prevent attacks such as cross-site scripting or SQL injection.

In particular, I think you're talking about cross-site scripting attacks. It seems that this node module (https://github.com/theSmaw/Caja-HTML-Sanitizer) may be suitable for what you're trying to achieve.

Stripping out all HTML tags is not necessarily a great idea. This is because event based cross-site scripting may still be possible. For example:

<a href="/yourprofilename">yourprofilename</a>

If the user has the ability to change the yourprofilename section, consider the following input:

" onfocus="prompt(document.location); autofocus"

This would turn the link into this:

<a href="/" onfocus="prompt(document.location);" autofocus">yourprofilename</a>

This would trigger cross-site scripting without the use of HTML tags.


SQL

Protection against SQL injections is done using prepared statements. Generally speaking, it is best practice to avoid manual concatenation of user generated strings in SQL statements.

Instead use the ? annotation and provide the input string as a parameter. The driver makes sure to block any SQL injection attempts, as well as unexpected user input.

MySQL example -

PreparedStatement ps = connection.prepareStatement("INSERT INTO tbl VALUES (?)");
ps.setString(1, "'abc'); TRAUNCATE TABLE users; SELECT (1");
ps.executeUpdate();

The injection attempt will fail.

XSS

You can HTML escape user generated strings or just replace < with &gt; and > with &lt;, before sending it to the client or when writing it to the database.

Also, check out the Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet guide.