Sanitizing input in Express using express-validator

By

Learn how to sanitize input in your Express app with express-validator, chaining methods like trim(), escape() and normalizeEmail() after validation.

~~~

You’ve seen how to validate input that comes from the outside world to your Express app.

There’s one thing you quickly learn when you run a public-facing server: never trust the input.

Even if you sanitize and make sure that people can’t enter weird things using client-side code, you’ll still be subject to people using tools (even just the browser devtools) to POST directly to your endpoints.

Or bots trying every possible combination of exploit known to humans.

What you need to do is sanitize your input.

The express-validator package you already use to validate input can also sanitize it. The code below uses Express 5, the current major, and express-validator 7:

npm install express@5 express-validator@7

The examples use ES modules, so add "type": "module" to your package.json. If you use CommonJS, swap each import for a require(). Everything else stays the same.

Say you have a POST endpoint that accepts the name, email and age parameters:

import express from 'express'

const app = express()

app.use(express.json())

app.post('/form', (req, res) => {
  const name  = req.body.name
  const email = req.body.email
  const age   = req.body.age
})

Keep express.json() in your app, because in Express 5 req.body is undefined without a body parser.

You might validate it using body():

import express from 'express'
import { body } from 'express-validator'

const app = express()

app.use(express.json())

app.post('/form', [
  body('name').isLength({ min: 3 }),
  body('email').isEmail(),
  body('age').isNumeric()
], (req, res) => {
  const name  = req.body.name
  const email = req.body.email
  const age   = req.body.age
})

You can add sanitization by chaining the sanitization methods after the validation ones:

app.post('/form', [
  body('name').isLength({ min: 3 }).trim().escape(),
  body('email').isEmail().normalizeEmail(),
  body('age').isNumeric().trim().escape()
], (req, res) => {
  //...
})

The sanitized values replace the originals in req.body. In the handler, req.body.name is already trimmed and escaped.

The chain runs in order. Here isNumeric() runs before trim(), so " 42 " fails validation. If you expect stray whitespace, put trim() first.

Here I used these methods:

Other sanitization methods:

These ones force the conversion to a format:

Like with custom validators, you can create a custom sanitizer.

In the callback function, return the sanitized value:

const sanitizeValue = value => {
  //sanitize...
}

app.post('/form', [
  body('value').customSanitizer(value => {
    return sanitizeValue(value)
  }),
], (req, res) => {
  const value  = req.body.value
})

Want me to talk about your product? You can sponsor this site.

~~~

Related posts about express: