GuardAPI Logo
GuardAPI

Fix NoSQL Injection in Hapi

NoSQL Injection in Hapi typically occurs when raw user input from 'request.payload', 'request.params', or 'request.query' is passed directly into a database filter. In Node.js ecosystems using MongoDB or Mongoose, attackers exploit the lack of type enforcement to inject operator objects like '{$gt: ""}' or '{$ne: null}'. This allows for authentication bypass, data exfiltration, and logic manipulation. If your route handlers don't validate that inputs are strings rather than objects, your database is an open book.

The Vulnerable Pattern

server.route({
  method: 'POST',
  path: '/api/login',
  handler: async (request, h) => {
    const { username, password } = request.payload;
    // VULNERABLE: If payload is { "username": "admin", "password": { "$ne": "" } }, 
    // the query becomes User.findOne({ username: 'admin', password: { $ne: '' } })
    // effectively logging in as admin without a password.
    const user = await User.findOne({ username, password });
    if (!user) return h.response({ error: 'Unauthorized' }).code(401);
    return { success: true };
  }
});

The Secure Implementation

The primary defense against NoSQL injection in Hapi is leveraging its built-in validation engine, Joi. The vulnerability stems from type confusion: the database driver accepts both strings and objects. By defining a strict Joi schema in the route's 'options.validate' block, you ensure that incoming data matches expected types. When Joi specifies 'Joi.string()', any attempt to pass a MongoDB operator object will fail validation. This 'Secure by Design' approach stops the attack at the framework level before the malicious payload ever reaches your database logic.

const Joi = require('joi');

server.route({ method: ‘POST’, path: ‘/api/login’, options: { validate: { // SECURE: Joi enforces that ‘username’ and ‘password’ MUST be strings. // If an attacker sends an object, Hapi returns a 400 Bad Request before the handler runs. payload: Joi.object({ username: Joi.string().min(3).max(30).required(), password: Joi.string().required() }), failAction: (request, h, err) => { throw err; } } }, handler: async (request, h) => { const { username, password } = request.payload; const user = await User.findOne({ username, password }); if (!user) return h.response({ error: ‘Unauthorized’ }).code(401); return { success: true }; } });

System Alert • ID: 2771
Target: Hapi API
Potential Vulnerability

Your Hapi API might be exposed to NoSQL Injection

74% of Hapi apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

Free Tier • No Credit Card • Instant Report

Verified by Ghost Labs Security Team

This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.