Fix NoSQL Injection in Fresh
Fresh is a high-performance Deno framework, but it doesn't shield you from NoSQL injection if you're piping raw request bodies into MongoDB or similar drivers. Attackers exploit these sinks by injecting operator objects (e.g., {"$gt": ""}) where the application expects a string. This allows for authentication bypass, data exfiltration, and unauthorized record modification. To fix this, we must enforce strict schema validation and type-casting at the edge.
The Vulnerable Pattern
export const handler: Handlers = {
async POST(req, _ctx) {
const { username, password } = await req.json();
// VULNERABLE: If an attacker sends {"username": {"$ne": null}}, the query returns the first user.
const user = await db.collection("users").findOne({ username, password });
if (user) return new Response("Logged In");
return new Response("Unauthorized", { status: 401 });
}
};
The Secure Implementation
The vulnerability stems from Deno's `req.json()` deserializing arbitrary objects. In the vulnerable snippet, an attacker can pass a JSON object instead of a string, which the MongoDB driver interprets as a query operator. The fix implements two layers of defense: 1) Schema validation using Zod to ensure inputs are strictly strings, which causes the parser to fail if an object/operator is provided. 2) Using the explicit `$eq` operator in the query, which forces the database to treat the input as a literal value even if the validation layer were somehow bypassed.
import { z } from "https://deno.land/x/zod/mod.ts";const UserSchema = z.object({ username: z.string(), password: z.string(), });
export const handler: Handlers = { async POST(req, _ctx) { try { const body = await req.json(); // SECURE: Zod enforces that username and password MUST be strings, stripping any injected objects. const { username, password } = UserSchema.parse(body);
// Explicitly using $eq prevents the driver from interpreting values as operators. const user = await db.collection("users").findOne({ username: { $eq: username }, password: { $eq: password } }); if (!user) return new Response("Unauthorized", { status: 401 }); return new Response("Logged In"); } catch (err) { return new Response("Invalid Input", { status: 400 }); }
} };
Your Fresh API
might be exposed to NoSQL Injection
74% of Fresh apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.
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.