# 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>

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>

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://www.securecoding.com/blog/using-helmetjs/>

<https://geshan.com.np/blog/2021/01/nodejs-express-helmet/>

Online Checker:<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>

* [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>

{% 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>

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

### CSURF

<https://www.npmjs.com/package/csurf>

protection against CSRF

### 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>

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

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

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://app-sec.gitbook.io/application-security/node.js-+-express.js-security-best-practices.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
