GuardAPI Logo
GuardAPI

Fix NoSQL Injection in Falcon

NoSQL Injection (NoSQLi) in Falcon/PyMongo stacks occurs when raw user input from 'req.media' or 'req.params' is passed directly into database query filters. Attackers leverage MongoDB query operators like '$gt', '$ne', or '$regex' to bypass authentication, dump collections, or perform blind data exfiltration. If you're passing a dictionary directly from a request into a find() call, you're pwned.

The Vulnerable Pattern

import falcon
from pymongo import MongoClient

client = MongoClient(‘mongodb://localhost:27017/’) db = client[‘prod_db’]

class LoginResource: def on_post(self, req, resp): # VULNERABLE: req.media is passed directly to find_one. # Attacker sends: {‘username’: ‘admin’, ‘password’: {‘$ne’: ‘wrong’}} # MongoDB returns the admin user because the password is ‘not equal’ to ‘wrong’. user_data = req.media user = db.users.find_one(user_data)

    if user:
        resp.media = {'status': 'authenticated', 'token': 'secret_session_blob'}
    else:
        raise falcon.HTTPUnauthorized(description='Invalid credentials')</code></pre>

The Secure Implementation

The vulnerability lies in the dynamic nature of BSON. When PyMongo receives a dictionary as a query parameter, it interprets keys starting with '$' as query operators. The fix is two-fold: 1. Use a Schema Validator (like Marshmallow or Pydantic) to enforce that input fields are strictly strings, which prevents the injection of nested objects/operators. 2. Never pass the raw input object to the driver; explicitly construct your query filter to ensure user input is treated as a literal value, not a command.

import falcon
from pymongo import MongoClient
from marshmallow import Schema, fields, ValidationError

SECURE: Define a strict schema to enforce types

class LoginSchema(Schema): username = fields.Str(required=True) password = fields.Str(required=True)

client = MongoClient(‘mongodb://localhost:27017/’) db = client[‘prod_db’]

class LoginResource: def on_post(self, req, resp): try: # Validate and sanitize: filters out any keys not in the schema (like $ne) data = LoginSchema().load(req.media)

        # Explicitly map fields to prevent operator injection
        user = db.users.find_one({
            'username': data['username'],
            'password': data['password']
        })
        
        if user:
            resp.media = {'status': 'authenticated'}
        else:
            resp.status = falcon.HTTP_401
    except ValidationError as err:
        raise falcon.HTTPBadRequest(description=str(err.messages))</code></pre>
System Alert • ID: 2367
Target: Falcon API
Potential Vulnerability

Your Falcon API might be exposed to NoSQL Injection

74% of Falcon 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.