express-mongo-sanitize
Express middleware that strips MongoDB operator injection payloads from req.body, req.query, req.params, and req.headers before they reach your database queries.
Repository Health
Technical Analysis
express-mongo-sanitize is a lightweight Express middleware that protects Node.js applications from MongoDB operator injection attacks. It scans req.body, req.query, req.params, and req.headers for keys that begin with $ or contain a . — the characters MongoDB reserves for query operators like $where, $gt, or $ne — and either strips them or replaces them with a safe character before your route handlers ever see them.
Beyond the middleware, the package exports sanitize() and has() functions so the same logic can run directly against arbitrary objects outside of an Express request cycle. Configurable options include replaceWith (substitute prohibited characters instead of deleting them), allowDots (permit dots for legitimate nested-document queries while still blocking $ operators), and dryRun paired with an onSanitize callback (detect without modifying, useful for staged rollouts) — making it a drop-in first line of defense for any Express + MongoDB stack.
What You Get
- Express middleware installed with a single
app.use(mongoSanitize())call that sanitizes body, query, params, and headers automatically - Standalone
sanitize()andhas()functions for sanitizing or detecting prohibited keys in any object, independent of Express - Configurable
replaceWithoption to substitute prohibited characters instead of deleting the offending keys outright allowDotsoption to permit legitimate dot-notation nested-document queries while still blocking$operator injectiondryRunmode paired with anonSanitizecallback for auditing which requests would be sanitized without mutating them
Common Use Cases
- Public-facing API protection - teams exposing Express + MongoDB APIs to untrusted clients add the middleware globally to block NoSQL operator injection before it reaches Mongoose or the native driver
- Login and search endpoint hardening - developers sanitize req.body and req.query on authentication and search routes specifically, where attackers commonly attempt
$whereor$neinjection to bypass logic - Migrating legacy Express apps to safer defaults - teams adopt
dryRunwithonSanitizefirst to log which requests would be affected, then enable real sanitization once they’ve confirmed no false positives - Building custom sanitization pipelines - projects that don’t use Express still import the
sanitize()andhas()helpers directly to clean data pulled from queues, files, or third-party webhooks before writing to MongoDB
Under The Hood
Architecture Single-file module (index.js) built around one recursive traversal helper, withEach(), that walks objects and arrays uniformly and delegates decision-making to a callback returning shouldRecurse and an optional renamed key; both the read-only has() check and the mutating _sanitize() implementation share this one traversal, keeping the two operations consistent by construction. The Express middleware wraps _sanitize() and applies it independently across the four request properties it cares about (body, params, headers, query), calling next() unconditionally and invoking an optional onSanitize callback per sanitized key. Because everything funnels through withEach() and _sanitize(), extending the matching rule or adding a new request property to sanitize would touch very few lines.
Tech Stack Plain, dependency-free Node.js — the package.json declares zero runtime dependencies, only devDependencies for tooling (mocha, chai, supertest, express, and body-parser for tests; eslint and prettier for style; tsd for type-testing). TypeScript consumers get hand-written ambient declarations (index.d.ts) rather than a compiled TS source. CI runs the test matrix across Node 10, 12, 14, and 16 via GitHub Actions.
Code Quality Test coverage is extensive relative to the source: a single ~130-line index.js is backed by an 1800+ line test suite covering the middleware, sanitize(), has(), and every option combination, run with mocha/chai/supertest; type correctness is separately verified with tsd against a dedicated type-test file. Prettier and ESLint are wired into npm scripts and enforced in CI. Naming is small and consistent, and the prototype-pollution guard (explicitly refusing to reassign proto, constructor, or prototype during replaceWith substitution) shows deliberate defensive coding rather than an afterthought.
API Design The public surface is intentionally small: a default export usable directly as Express middleware, plus sanitize() and has() static methods for use outside of Express entirely. The common case needs no configuration at all (app.use(mongoSanitize())), while replaceWith, allowDots, dryRun, and onSanitize cover the realistic variations teams need, each documented in the README with a runnable example. Hand-authored TypeScript definitions give typed autocomplete without requiring a TS build step from consumers.