Skip to content

Middleware Security Patterns — Complete Implementation Guide

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about Middleware Security Patterns. We cover key concepts, practical examples, and best practices to help you master this topic.

Middleware security patterns protect your application by filtering, validating, and sanitizing every request before it reaches your business logic, preventing common web attacks at the pipeline level.

What You'll Learn

By the end of this tutorial, you will implement security middleware that prevents SQL injection, XSS Attacks, CSRF Attacks, and request smuggling, and applies security headers to every response.

Why It Matters

Security vulnerabilities in middleware leave your entire application exposed. DodaTech's Durga Antivirus Pro backend uses security middleware to inspect and sanitize all incoming data.

Real-World Use

Durga Antivirus Pro's scan submission API uses security middleware to sanitize filenames, validate file types, limit request sizes, and prevent path traversal attacks before any file is processed.

Security Middleware Learning Path

flowchart LR
  A[Performance Middleware] --> B[Security Middleware]
  B --> C[Input Sanitization]
  B --> D[Attack Prevention]
  B --> E{You Are Here}
  style E fill:#f90,color:#fff

Input Sanitization Middleware

Input sanitization strips or escapes dangerous characters from request data to prevent injection attacks before they reach your application.

const express = require("express");
const app = express();

app.use(express.json());

function sanitizeInput(req, res, next) {
  if (req.body) {
    for (const key in req.body) {
      if (typeof req.body[key] === "string") {
        req.body[key] = req.body[key]
          .replace(/</g, "&lt;")
          .replace(/>/g, "&gt;")
          .replace(/"/g, "&quot;")
          .replace(/'/g, "&#x27;");
      }
    }
  }
  next();
}

app.post("/comment", sanitizeInput, (req, res) => {
  res.json({ sanitized: req.body.comment });
});

app.listen(3000);

Expected output for POST /comment with <script>alert('xss')</script>:

{"sanitized": "&lt;script&gt;alert(&#x27;xss&#x27;)&lt;/script&gt;"}

SQL Injection Prevention

SQL injection middleware inspects query parameters and body fields for SQL patterns and rejects requests that contain them.

const express = require("express");
const app = express();

const SQL_PATTERNS = [
  /(\bSELECT\b.*\bFROM\b)/i,
  /(\bDROP\b.*\bTABLE\b)/i,
  /(\bDELETE\b.*\bFROM\b)/i,
  /(\bINSERT\b.*\bINTO\b)/i,
  /(\bUNION\b.*\bSELECT\b)/i,
  /(--)/,
  /(\bOR\b\s+\d+\s*=\s*\d+)/i
];

function preventSQLInjection(req, res, next) {
  const checkValue = (value) => {
    if (typeof value === "string") {
      for (const pattern of SQL_PATTERNS) {
        if (pattern.test(value)) {
          return true;
        }
      }
    }
    return false;
  };

  const checkObject = (obj) => {
    for (const key in obj) {
      if (checkValue(obj[key])) return true;
    }
    return false;
  };

  if (req.query && checkObject(req.query)) {
    return res.status(400).json({ error: "Invalid query parameters" });
  }

  if (req.body && checkObject(req.body)) {
    return res.status(400).json({ error: "Invalid request body" });
  }

  next();
}

app.use(express.json());
app.use(preventSQLInjection);

app.get("/users", (req, res) => {
  res.json({ users: [] });
});

app.listen(3000);

Expected output for GET /users?name=Robert'); DROP TABLE Students;--:

{"error": "Invalid query parameters"}

CSRF Protection

Cross-Site Request Forgery (CSRF) protection middleware ensures that requests to state-changing endpoints originate from your own frontend, not from malicious sites.

const express = require("express");
const csrf = require("csurf");
const cookieParser = require("cookie-parser");
const app = express();

app.use(cookieParser());
app.use(express.urlencoded({ extended: true }));

const csrfProtection = csrf({ cookie: true });

app.get("/form", csrfProtection, (req, res) => {
  res.send(`
    <form method="POST" action="/transfer">
      <input type="hidden" name="_csrf" value="${req.csrfToken()}">
      <input type="text" name="amount">
      <button type="submit">Transfer</button>
    </form>
  `);
});

app.post("/transfer", csrfProtection, (req, res) => {
  res.json({ transferred: req.body.amount });
});

app.use((err, req, res, next) => {
  if (err.code === "EBADCSRFTOKEN") {
    return res.status(403).json({ error: "Invalid CSRF token" });
  }
  next(err);
});

app.listen(3000);

Common Mistakes

  1. Relying on client-side validation — Client validation is for UX, not security. Always validate and sanitize on the server.

  2. Blacklisting instead of whitelisting — Blocking known bad patterns is fragile. Whitelist allowed patterns for stronger security.

  3. Not limiting request body size — An attacker can send a multi-gigabyte request body and exhaust memory. Set body size limits.

  4. Exposing stack traces in error responses — Stack traces reveal code structure. Return generic error messages to clients.

  5. Not validating Content-Type — An attacker can send JSON to a form endpoint or vice versa. Validate Content-Type matches expectations.

Practice Questions

  1. Why is input sanitization important in middleware? It prevents injection attacks (XSS, SQLi) from reaching business logic, protecting your application and users.

  2. What is the difference between sanitization and validation? Validation rejects invalid data. Sanitization modifies data to make it safe while preserving its meaning.

  3. How does CSRF protection work? It generates a unique token for each form session. The server rejects submissions without a valid token.

  4. Challenge: Build middleware that detects and blocks path traversal attacks in file paths.

function preventPathTraversal(req, res, next) {
  const path = req.query.file || req.body.file;
  if (path && (path.includes("..") || path.includes("/"))) {
    return res.status(400).json({ error: "Invalid path" });
  }
  next();
}

FAQ

Can middleware prevent all attacks?

No single layer prevents all attacks. Security middleware is one layer in a defense-in-depth strategy.

Should I use helmet for security headers?

Yes. Helmet is the standard for HTTP security headers. It is maintained by the Express team.

How do I prevent brute force attacks with middleware?

Combine rate limiting with authentication middleware. Block IPs after too many failed login attempts.

Is input sanitization enough to prevent XSS?

No. Use Content-Security-Policy headers, output encoding, and input sanitization together for XSS prevention.

How often should I update security middleware?

Monitor for security advisories. Update immediately for critical vulnerabilities. Review security middleware quarterly.

Mini Project

Build a comprehensive security middleware pipeline with input sanitization, SQL injection prevention, Rate Limiting, secure headers, and request size limiting.

const express = require("express");
const helmet = require("helmet");
const rateLimit = require("express-rate-limit");
const app = express();

app.use(helmet());
app.use(express.json({ limit: "1mb" }));

const limiter = rateLimit({
  windowMs: 60000,
  max: 100,
  message: { error: "Too many requests" }
});
app.use(limiter);

function sanitize(req, res, next) {
  if (req.body) {
    for (const key in req.body) {
      if (typeof req.body[key] === "string") {
        req.body[key] = req.body[key].replace(/<[^>]*>/g, "");
      }
    }
  }
  next();
}

app.post("/submit", sanitize, (req, res) => {
  res.json({ received: req.body });
});

app.listen(3000);

What's Next

Now that you understand middleware security, apply everything in the comprehensive middleware project. Then explore rate limiting patterns in depth.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro