Security Best Practices

A checklist of habits that keep an Express app safe in production.

Security is layered. Combine these habits:

  • Use helmet() for secure headers.
  • Validate and sanitize all input.
  • Keep secrets in environment variables, never in code or git.
  • Hash passwords with bcrypt; never store them in plain text.
  • Serve everything over HTTPS.
  • Apply rate limiting to auth and public endpoints.
  • Keep dependencies updated; run npm audit.

Example

Example · javascript
const bcrypt = require('bcrypt');

app.post('/register', async (req, res) => {
  const hash = await bcrypt.hash(req.body.password, 12);
  // store 'hash', never the raw password
  res.status(201).json({ ok: true });
});

When to use it

  • A security audit checklist for an Express API includes verifying that Helmet is active, JWT secrets are not hard-coded, and rate limiting is on all public routes.
  • A developer avoids sending stack traces to clients in production by checking process.env.NODE_ENV inside the error middleware.
  • A team sets the X-Powered-By header to disabled using app.disable('x-powered-by') to prevent fingerprinting the tech stack.

More examples

Disable X-Powered-By header

Disables the X-Powered-By: Express header and adds Helmet, removing two common fingerprinting vectors.

Example · js
const express = require('express');
const app = express();

app.disable('x-powered-by'); // don't advertise Express
app.use(require('helmet')());

app.get('/', (req, res) => res.send('OK'));
app.listen(3000);

Hide error details in production

Includes the stack trace in error responses only in development mode, hiding implementation details from production clients.

Example · js
app.use((err, req, res, next) => {
  const isDev = process.env.NODE_ENV !== 'production';
  res.status(err.status || 500).json({
    error: err.message,
    ...(isDev && { stack: err.stack }),
  });
});

Prevent parameter pollution

Layers hpp (HTTP parameter pollution prevention), Helmet, rate limiting, and a body-size cap to harden the app comprehensively.

Example · js
const hpp = require('hpp');
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const express = require('express');
const app = express();

app.use(helmet());
app.use(hpp());          // removes duplicate query params
app.use(rateLimit({ windowMs: 15*60*1000, max: 200 }));
app.use(express.json({ limit: '10kb' }));  // cap body size

app.listen(3000);

Discussion

  • Be the first to comment on this lesson.