AI Security Summary
Express/Node.js apps are most exposed through ORM/ODM query construction and file-upload parsing layers. The recurring mistake is passing unsanitized user input directly into query builders, template engines, or multipart parsers without strict type or schema validation.
Prototype Pollution via Object Path Manipulation
Covers: CVE-2022-24304 · CVE-2023-3696 · CVE-2022-2564 · CVE-2025-13465 · CVE-2026-2950 Risk: Attackers pollute Object.prototype through ORM schema setters and utility path functions, enabling DoS or logic corruption across the entire application.
- NEVER pass user-controlled strings as schema path names or object key paths without first validating against an explicit allowlist.
- ALWAYS treat proto, constructor, and prototype as forbidden keys in any object merge, path-set, or schema-registration code path.
- NEVER use lodash path-based functions (unset, omit, set, get) with user-supplied path segments, including array-wrapped segments.
- ALWAYS freeze or seal shared prototype objects that are populated from external input at startup.
- NEVER rely on a single string-key guard to block prototype pollution; validate both string and array path forms.
Code and Command Injection via Template and Query Execution Sinks
Covers: CVE-2021-23337 · CVE-2026-4800 · CVE-2025-23061 · CVE-2024-53900 Risk: User input reaching lodash template imports or Mongoose $where clauses is executed as JavaScript, enabling arbitrary code execution and unauthorized data access.
- NEVER pass user-controlled values as lodash template variable names, imports keys, or any option that flows into a Function() constructor.
- NEVER use the MongoDB $where operator with any value derived from user input; use aggregation pipeline expressions instead.
- ALWAYS validate that template options objects (variable, imports) originate exclusively from trusted, static configuration.
- NEVER allow query operators from user-supplied JSON to reach the database engine without strict operator allowlisting.
- ALWAYS use parameterized query builders rather than JavaScript-evaluating query clauses for dynamic filter conditions.
SQL Injection via ORM Query Builder Trust in Raw Input
Covers: CVE-2023-22578 · CVE-2023-22579 · CVE-2023-25813 · CVE-2023-22580 · CVE-2026-30951 · CVE-2026-42334 Risk: Sequelize and Mongoose silently accept raw SQL fragments, invalid where values, and unsanitized cast types, allowing attackers to inject and exfiltrate arbitrary data.
- NEVER pass user-controlled strings inside parentheses to Sequelize attribute arrays; always use literal column identifiers.
- NEVER use Sequelize replacements mixed with literal() in the same query without validating every interpolated value against a strict type contract.
- ALWAYS validate that where option values are plain objects or primitives before passing them to any ORM finder; reject Date, function, or class instances.
- NEVER allow user-supplied JSON object keys to flow into Sequelize JSON/JSONB cast-type positions; strip or reject any key containing '::'.
- ALWAYS enable Mongoose sanitizeFilter and verify that all logical operators including $nor are covered by your sanitization layer.
- NEVER rely on ORM-level sanitization alone; enforce a schema-validation layer before query construction.
JWT Algorithm Confusion and Signature Bypass
Covers: CVE-2022-23539 · CVE-2022-23540 · CVE-2022-23541 Risk: Misconfigured jwt.verify() calls accept the none algorithm or allow RSA public keys to be reused as HMAC secrets, letting attackers forge valid-looking tokens.
- ALWAYS explicitly specify the expected algorithm(s) in the jwt.verify() options object; never omit the algorithms field.
- NEVER allow the none algorithm in any jwt.verify() call, even as a fallback.
- NEVER use an asymmetric public key as the secret in a symmetric HMAC verification path.
- ALWAYS enforce that the key type in use is consistent with the declared algorithm before verification proceeds.
- NEVER accept tokens whose header algorithm differs from the algorithm your application explicitly configured.
Multipart Upload Denial of Service via Malformed Requests and Unclosed Streams
Covers: CVE-2025-47935 · CVE-2025-47944 · CVE-2025-48997 · CVE-2025-7338 · CVE-2026-2359 · CVE-2026-3304 · CVE-2026-3520 · CVE-2020-28500 · CVE-2024-29041 Risk: Malformed multipart requests, empty field names, dropped connections, and deeply nested inputs can crash the Node.js process or exhaust memory via unclosed streams and unhandled exceptions.
- ALWAYS attach error handlers to every incoming request stream and busboy/multer stream to prevent unclosed stream accumulation.
- NEVER allow multipart field names or file names to reach parsing logic without a non-empty string validation guard.
- ALWAYS enforce explicit limits on field count, field name length, file count, and file size in multer configuration.
- NEVER trust that a multipart middleware will handle all malformed or prematurely terminated connections gracefully; wrap upload routes in process-safe error boundaries.
- ALWAYS validate and sanitize user-supplied URLs before passing them to res.redirect(); reject any URL whose protocol is not explicitly http or https.
- NEVER pass user-controlled input to lodash toNumber, trim, or trimEnd without bounding the input length to prevent ReDoS.
Cross-cutting patterns (all Express / Node.js projects)
- NEVER trust the shape or type of any value arriving from an HTTP request body, query string, or header without explicit schema validation before it reaches any ORM, template engine, or stream parser.
- ALWAYS use an explicit allowlist of permitted operators, keys, and value types at the application boundary rather than relying on library-internal sanitization.
- NEVER construct dynamic identifiers, cast types, or path segments by concatenating or interpolating user-supplied strings; always resolve them through a controlled lookup map.
- ALWAYS attach top-level unhandledRejection and uncaughtException handlers that log and gracefully drain connections rather than allowing a single malformed request to crash the process.