---
description: >-
  Intended as a security checklist for production ready applications. stuff like
  security dependencies, best practices, and hanging fruits.
---

# Node.js + Express.js Security Best Practices

#### IDE Recommendations

[eslint-plugin-security](https://github.com/nodesecurity/eslint-plugin-security)

Snyk IDE

### Up to date versions

[https://expressjs.com/en/advanced/best-practice-security.html#dont-use-deprecated-or-vulnerable-versions-of-express](https://expressjs.com/en/advanced/best-practice-security.html#dont-use-deprecated-or-vulnerable-versions-of-express)

not really need Snyk, just make sure express npm, Node doesn’t use out-of-date versions

use&#x20;

`Snyk audit`

### Using TLS

[https://expressjs.com/en/advanced/best-practice-security.html#use-tls](https://expressjs.com/en/advanced/best-practice-security.html#use-tls)

Make sure the application uses TLS, HTTPS,

* verify certificate, and renewal automation scripts
* Test production website against the CA

### Use of Helmet

[https://expressjs.com/en/advanced/best-practice-security.html#use-helmet](https://expressjs.com/en/advanced/best-practice-security.html#use-helmet)

[https://www.securecoding.com/blog/using-helmetjs/](https://www.securecoding.com/blog/using-helmetjs/)

[https://geshan.com.np/blog/2021/01/nodejs-express-helmet/](https://geshan.com.np/blog/2021/01/nodejs-express-helmet/)

Online Checker:[http://cyh.herokuapp.com/cyh](http://cyh.herokuapp.com/cyh).

* **Strict-Transport-Security** enforces secure (HTTP over SSL/TLS) connections to the server
* **X-Frame-Options** provides [clickjacking](https://www.owasp.org/index.php/Clickjacking) protection
* **X-XSS-Protection** enables the Cross-site scripting (XSS) filter built into most recent web browsers
* **X-Content-Type-Options** prevents browsers from MIME-sniffing a response away from the declared content-type
* **Content-Security-Policy** prevents a wide range of attacks, including Cross-site scripting and other cross-site injections
* `helmet.contentSecurityPolicy` which sets the `Content-Security-Policy` header. This helps prevent cross-site scripting attacks among many other things.
* `helmet.hsts` which sets the `Strict-Transport-Security` header. This helps enforce secure (HTTPS) connections to the server.
* `helmet.frameguard` which sets the `X-Frame-Options` header. This provides [clickjacking](https://www.owasp.org/index.php/Clickjacking) protection.

```
const helmet = require('helmet')
app.use(helmet())
```

> Without helmet use: `app.disable('x-powered-by')`
>
> ```
> # nginx.conf
>
> add_header X-Frame-Options SAMEORIGIN;
> add_header X-Content-Type-Options nosniff;
> add_header X-XSS-Protection "1; mode=block";
> add_header Content-Security-Policy "default-src 'self'";
> ```

### JWT

Most secure (though not always practical) use of JWT tokens:

General Best Practice

* tokens used for authorization, but not session management
* short lived (few minutes)
* expected to be used once (confirm authentication/authorization and get a session ID)
* **memory-only JWT token handling**

Applied Best Practice

* algorithm must be explicitly selected
* validate all signatures
* key generating libraries should rely on cryptographic-quality pseudo-random number generators (PRNGs
* **Use Different Validation Rules For Each Token**
  * rather than using the same private key for signing all kinds of tokens, consider using different private keys for each subsystem of your architecture
* **Use The `typ` Claim To Separate Types Of Tokens**

### **Use cookies securely**

[https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely)

* [express-session](https://www.npmjs.com/package/express-session) that replaces `express.session` middleware built-in to Express 3.x.
* [cookie-session](https://www.npmjs.com/package/cookie-session) that replaces `express.cookieSession` middleware built-in to Express 3.x.

```
const session = require('express-session')
app.set('trust proxy', 1) // trust first proxy
app.use(session({
  secret: 's3Cur3',
  name: 'sessionId'
}))
```

### Rate limiting

[https://expressjs.com/en/advanced/best-practice-security.html#prevent-brute-force-attacks-against-authorization](https://expressjs.com/en/advanced/best-practice-security.html#prevent-brute-force-attacks-against-authorization)

{% embed url="https://github.com/animir/node-rate-limiter-flexible" %}

Baseline for limiting:

1. Number of consecutive failed attempts by the same user name and IP address.
2. Number of failed attempts from an IP address over some long period of time. For example, block an IP address if it makes 100 failed attempts in one day.

### SQL injection, using parameterized queries or prepared statements

> Lookup ‘Database.Query(’

#### mitigation

[https://www.npmjs.com/package/pg](https://www.npmjs.com/package/pg)

```
var q = 'SELECT name FROM books WHERE id = $1';
client.query(q, ['3'], function(err, result) {});
```

### CSURF

[https://www.npmjs.com/package/csurf](https://www.npmjs.com/package/csurf)

protection against CSRF

### Regex

[https://www.npmjs.com/package/safe-regex](https://www.npmjs.com/package/safe-regex)

### User input Filtering and Sanitization

[express-validator](https://express-validator.github.io/docs/) and [express-sanitize-input](https://flaviocopes.com/express-sanitize-input/)

[https://www.npmjs.com/package/string-sanitizer](https://www.npmjs.com/package/string-sanitizer)

{% embed url="https://github.com/pocketly/node-sanitize" %}

```jsx
var sanitizer = require('sanitize')();

 var name = sanitizer.value(req.name, 'string');
```
