Like any kind of apps, JavaScript apps also have to be written well.
Otherwise, we run into all kinds of issues later on.
In this article, we’ll look at some best practices we should follow when writing Node apps.
Enable TLS/SSL
This is the most basic security best practice.
We don’t anyone snooping at the data that is being sent and received.
It’s also important because it can ensure that the data isn’t modified during transit.
We can install a SSL certificate with any web host.
Let’s Encrypt provides us with free SSL certificates that can be renewed automatically.
Also, our Node app shouldn’t be exposed directly to the Internet even though we’re communicating through SSL.
For example, we can write:
app.set(‘trust proxy’, ‘1.0.0.0’);
to let traffic from our proxy to our app.
Then we can use this in addition to a reverse proxy like Nginx to put our app being a reverse proxy.
The proxy should also set the X-Forwarded-Proto: https
HTTP header.
Test HTTPS Certificate Transmission
We can test HTTPS certificate transmission with Qualys SSL Labs, nmap, OpenSSL or sslyze.
We can run nmap by running:
nmap --script ss-cert,ssl-enum-ciphers -p 443 example.com
We test SSL transmission with these options.
example.com
is our site.
443 is the port that SSL communicates through.
With sslyze, we run:
sslyze.py --regular example.com:4444
With the OpenSSL client, we run:
echo ‘q’ | openssl s_client -host example.com -port 443
Check for Known Security Vulnerabilities
We should keep up to date with the latest known security vulnerabilities.
We can check our dependencies form them with a few tools. They include websites like Snyk, Node Security Project, and Retire.js.
Encode All Untrusted Data Sent to an Application
To keep untrusted data from running anything malicious, we should sanitize them so that they can’t be run as code.
There’re a few ways to encode them.
HTML encoding can be done with the escape-html package on the back end.
Anything that’s within a tag is escaped.
CSS Encoding can be done with the css.escape library.
JavaScript encoding can be done with the js-string-escape library, which works on both the browser and with Node.
To escape URLs, we can use the encodeURIComponent
function escape them on the front end.
And urlencode
can be used on the back end.
Prevent Parameter Pollution to Stop Possible Uncaught Exceptions
We should prevent parameter pollution which can generate possible exceptions.
If we have unexpected data types for the parsed query string, then we may get exceptions when they’re parsed and we try to do something with them.
For instance, if we have the given endpoint:
app.get('/foo', function(req, res){
if(req.query.name){
res.status(200).send(req.query.name.toUpperCase())
} else {
res.status(200).send('Hi');
}
});
Then if we make the query to:
http://example.com:8080/foo?name=james&name=mary
Then req.query.name
will be an array since we have 2 values with the key name
.
Array has no toUpperCase
method so we’ll have an error.
Therefore, we should check for that so that we can stop the toUpperCase
method from being called if req.query.name
is an array.
Conclusion
We should enable SSL/TLS with any app. We can get an SSL certificate for free.
Also, we should check our data and escape them.
And we should check for security vulnerabilities.