Here are the nodejs security checklists

Remove the x-powered-by header

Normally if you see the requests, there is x-powered-by header. For a expressjs server, it would be x-powered-by:Express. This can help attacker know the server side technology.

Remedy

Disable the x-powered-by header.

app.use(function(req,res,next){

/*Remove the x-powered-by header */ res.removeHeader('X-Powered-By')

})

Clickjacking

If somebody can embed your site in iframe and display it inside his evil site, then it can be used to steal user data. Simply deny iframing your site by using the header X-Frame-Options

res.setHeader('X-Frame-Options', value)

Cache

Cache can store the webpage for faster viewing. The webpage are sometimes completely shown from cache without any calls to server. So a user logout from your site, and still press Back and see the authorized page. This can be prevented by disabling the cache altogether.

res.setHeader('X-Frame-Options', 'Deny')

Content security policy

By adding content security policy headers in your server response, you tell the browser which content has to be shown and what not. For example if you pass the content security header as

Content-Security-Policy: script-src 'self'

It will not allow execution of scripts inline. If you want to allow inline scripts, then you need to specify it explicitly.

Content-Security-Policy: script-src 'self' 'unsafe-inline'

You can read about other tags and values at Mozilla docs

Cross-Site Request Forgery

CSRF protects against post request (not only post, generally all request other than GET,HEAD and OPTIONS ) which did not originate from your site.

For example, you have a form, and api to handle the form data. At api /getform, you render the form. At api /postformdata, you handle the post data. But if somebody directly sends a POST request to your site, then it should not accept it. Why? Because the attacker might have hacked the user's session, and sending unauthorized POST requests from user's system, without their knowledge.

It can cause serious troubles when POST request can lead to transfer of funds, or some other important action.

In order to prevent such attacks, a simple solution is to create a token which is either unique for user's session, or for every GET request, and send that token along with the GET request.

When the user submits the form, the token is also sent. You can then verify that the token sent to GET request is same as you got in POST request.

Generally, these tokens are use cryptographic functions like SHA, and do not require database connection. You can read more about CSRF at our post here.

General procedure for CSRF is as follows

  1. When the user visits /getform, create a token. Set that token in user's browser as cookie, or pass it as variable (if server side rendering).
  2. In the form, add an hidden input field which contains the token. If the token is stored in cookie, then there is no need to add hidden input field.
  3. When submitting the form, just make sure that you send the token too. If you have added the token as form field, then it would be sent automatically.
  4. Verify the token integrity at the backend before processing the form.