cors vs helmet vs express-rate-limit vs csurf
Node.js Security Middleware Comparison
1 Year
corshelmetexpress-rate-limitcsurfSimilar Packages:
What's Node.js Security Middleware?

In Node.js web development, security is paramount, and various middleware packages are available to enhance the security posture of applications. These packages provide functionalities such as handling Cross-Origin Resource Sharing (CORS), preventing Cross-Site Request Forgery (CSRF), rate limiting requests to mitigate abuse, and securing HTTP headers. Implementing these middleware solutions helps protect applications from common web vulnerabilities, ensuring a safer environment for users and data.

Package Weekly Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
cors14,598,4726,107-306 years agoMIT
helmet3,674,52210,345103 kB15 months agoMIT
express-rate-limit1,439,4503,029124 kB73 months agoMIT
csurf495,6252,306-205 years agoMIT
Feature Comparison: cors vs helmet vs express-rate-limit vs csurf

Security Features

  • cors:

    CORS enables servers to specify which origins are permitted to access resources, thus preventing unauthorized cross-origin requests and enhancing security by controlling resource sharing.

  • helmet:

    Helmet sets various HTTP headers to secure your application, including Content Security Policy (CSP), X-Content-Type-Options, and X-Frame-Options, which help mitigate risks like clickjacking and MIME type sniffing.

  • express-rate-limit:

    Rate limiting helps prevent abuse by restricting the number of requests a client can make in a given timeframe, reducing the risk of brute-force attacks and server overload.

  • csurf:

    CSRF protection ensures that state-changing requests are validated against a token that is unique to the user session, effectively preventing unauthorized actions from being executed on behalf of the user.

Implementation Complexity

  • cors:

    Implementing CORS is relatively straightforward, requiring minimal configuration to specify allowed origins, methods, and headers, making it easy to integrate into existing applications.

  • helmet:

    Helmet is easy to implement, usually requiring just a single line of code to add to your middleware stack, allowing for quick enhancement of security without extensive configuration.

  • express-rate-limit:

    Setting up rate limiting is simple, with options to configure limits based on IP addresses, making it easy to integrate into existing middleware stacks without much overhead.

  • csurf:

    CSRF protection requires additional setup, including generating and validating tokens, which can add complexity to forms and AJAX requests, but significantly enhances security.

Performance Impact

  • cors:

    CORS can introduce slight latency due to preflight requests for certain types of requests, but the impact is generally minimal compared to the security benefits it provides.

  • helmet:

    Helmet has a minimal performance impact as it primarily modifies HTTP headers, which does not significantly affect response times.

  • express-rate-limit:

    Rate limiting can impact performance if not configured properly, but it is essential for maintaining server health and preventing abuse, making the trade-off worthwhile.

  • csurf:

    CSRF protection may add overhead due to token generation and validation, but this is typically negligible compared to the security it ensures against unauthorized actions.

Use Cases

  • cors:

    CORS is essential for APIs that are accessed by web applications hosted on different domains, making it crucial for modern web architectures that rely on microservices.

  • helmet:

    Helmet is a general-purpose security middleware that should be used in all web applications to enhance security through proper HTTP header management.

  • express-rate-limit:

    Rate limiting is particularly useful for public APIs and login endpoints to prevent brute-force attacks and ensure fair usage among clients.

  • csurf:

    CSRF protection is vital for applications that involve user sessions and state changes, such as banking applications or any site where users can submit forms.

Community and Support

  • cors:

    CORS is widely used and well-documented, with a large community providing support and examples for various use cases.

  • helmet:

    Helmet is a standard security practice in Node.js applications, with robust documentation and community support to guide developers in implementing best practices.

  • express-rate-limit:

    This package is popular in the Node.js community, with extensive documentation and examples available to assist in setup and configuration.

  • csurf:

    CSRF protection has strong community backing, with numerous resources available for implementation and troubleshooting, ensuring developers can find help easily.

How to Choose: cors vs helmet vs express-rate-limit vs csurf
  • cors:

    Choose CORS if your application needs to handle cross-origin requests, allowing specific domains to access resources on your server while preventing unauthorized access.

  • helmet:

    Use Helmet if you want to secure your HTTP headers, providing a set of middleware functions that help protect your app from common vulnerabilities by setting various HTTP headers.

  • express-rate-limit:

    Opt for Express Rate Limit if you want to control the rate of requests to your server, helping to prevent abuse and denial-of-service attacks by limiting the number of requests from a single IP address.

  • csurf:

    Select CSURF if your application requires protection against CSRF attacks, particularly for state-changing operations like form submissions, ensuring that requests are legitimate and originate from your application.

README for cors

cors

NPM Version NPM Downloads Build Status Test Coverage

CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.

Follow me (@troygoode) on Twitter!

Installation

This is a Node.js module available through the npm registry. Installation is done using the npm install command:

$ npm install cors

Usage

Simple Usage (Enable All CORS Requests)

var express = require('express')
var cors = require('cors')
var app = express()

app.use(cors())

app.get('/products/:id', function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for all origins!'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

Enable CORS for a Single Route

var express = require('express')
var cors = require('cors')
var app = express()

app.get('/products/:id', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a Single Route'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

Configuring CORS

var express = require('express')
var cors = require('cors')
var app = express()

var corsOptions = {
  origin: 'http://example.com',
  optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}

app.get('/products/:id', cors(corsOptions), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for only example.com.'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

Configuring CORS w/ Dynamic Origin

var express = require('express')
var cors = require('cors')
var app = express()

var whitelist = ['http://example1.com', 'http://example2.com']
var corsOptions = {
  origin: function (origin, callback) {
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  }
}

app.get('/products/:id', cors(corsOptions), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

If you do not want to block REST tools or server-to-server requests, add a !origin check in the origin function like so:

var corsOptions = {
  origin: function (origin, callback) {
    if (whitelist.indexOf(origin) !== -1 || !origin) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  }
}

Enabling CORS Pre-Flight

Certain CORS requests are considered 'complex' and require an initial OPTIONS request (called the "pre-flight request"). An example of a 'complex' CORS request is one that uses an HTTP verb other than GET/HEAD/POST (such as DELETE) or that uses custom headers. To enable pre-flighting, you must add a new OPTIONS handler for the route you want to support:

var express = require('express')
var cors = require('cors')
var app = express()

app.options('/products/:id', cors()) // enable pre-flight request for DELETE request
app.del('/products/:id', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for all origins!'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

You can also enable pre-flight across-the-board like so:

app.options('*', cors()) // include before other routes

Configuring CORS Asynchronously

var express = require('express')
var cors = require('cors')
var app = express()

var whitelist = ['http://example1.com', 'http://example2.com']
var corsOptionsDelegate = function (req, callback) {
  var corsOptions;
  if (whitelist.indexOf(req.header('Origin')) !== -1) {
    corsOptions = { origin: true } // reflect (enable) the requested origin in the CORS response
  } else {
    corsOptions = { origin: false } // disable CORS for this request
  }
  callback(null, corsOptions) // callback expects two parameters: error and options
}

app.get('/products/:id', cors(corsOptionsDelegate), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

Configuration Options

  • origin: Configures the Access-Control-Allow-Origin CORS header. Possible values:
    • Boolean - set origin to true to reflect the request origin, as defined by req.header('Origin'), or set it to false to disable CORS.
    • String - set origin to a specific origin. For example if you set it to "http://example.com" only requests from "http://example.com" will be allowed.
    • RegExp - set origin to a regular expression pattern which will be used to test the request origin. If it's a match, the request origin will be reflected. For example the pattern /example\.com$/ will reflect any request that is coming from an origin ending with "example.com".
    • Array - set origin to an array of valid origins. Each origin can be a String or a RegExp. For example ["http://example1.com", /\.example2\.com$/] will accept any request from "http://example1.com" or from a subdomain of "example2.com".
    • Function - set origin to a function implementing some custom logic. The function takes the request origin as the first parameter and a callback (which expects the signature err [object], allow [bool]) as the second.
  • methods: Configures the Access-Control-Allow-Methods CORS header. Expects a comma-delimited string (ex: 'GET,PUT,POST') or an array (ex: ['GET', 'PUT', 'POST']).
  • allowedHeaders: Configures the Access-Control-Allow-Headers CORS header. Expects a comma-delimited string (ex: 'Content-Type,Authorization') or an array (ex: ['Content-Type', 'Authorization']). If not specified, defaults to reflecting the headers specified in the request's Access-Control-Request-Headers header.
  • exposedHeaders: Configures the Access-Control-Expose-Headers CORS header. Expects a comma-delimited string (ex: 'Content-Range,X-Content-Range') or an array (ex: ['Content-Range', 'X-Content-Range']). If not specified, no custom headers are exposed.
  • credentials: Configures the Access-Control-Allow-Credentials CORS header. Set to true to pass the header, otherwise it is omitted.
  • maxAge: Configures the Access-Control-Max-Age CORS header. Set to an integer to pass the header, otherwise it is omitted.
  • preflightContinue: Pass the CORS preflight response to the next handler.
  • optionsSuccessStatus: Provides a status code to use for successful OPTIONS requests, since some legacy browsers (IE11, various SmartTVs) choke on 204.

The default configuration is the equivalent of:

{
  "origin": "*",
  "methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
  "preflightContinue": false,
  "optionsSuccessStatus": 204
}

For details on the effect of each CORS header, read this article on HTML5 Rocks.

Demo

A demo that illustrates CORS working (and not working) using jQuery is available here: http://node-cors-client.herokuapp.com/

Code for that demo can be found here:

License

MIT License

Author

Troy Goode (troygoode@gmail.com)