GuardAPI Logo
GuardAPI

Fix SQL Injection (Legacy & Modern) in Next.js

Next.js applications, whether using legacy /api routes or modern Server Actions, are prime targets for SQLi if you're concatenating strings like it's 2005. The shift to the server-side doesn't negate the need for input sanitization; it just moves the execution context. If you're raw-dogging database queries with template literals, you're giving attackers a direct shell to your data. Whether you're using 'mysql2', 'pg', or 'sqlite3', the fundamental failure is the same: mixing control plane (SQL commands) with data plane (user input).

The Vulnerable Pattern

'use server';
import { db } from '@/lib/db';

// VULNERABLE: Modern Server Action using string interpolation export async function searchUsers(query) { // An attacker can pass: ”’ OR 1=1 —” const sql = SELECT * FROM users WHERE username = '${query}'; const [rows] = await db.execute(sql); return rows; }

// VULNERABLE: Legacy API Route export default async function handler(req, res) { const { id } = req.query; const result = await db.query(SELECT * FROM posts WHERE id = ${id}); res.status(200).json(result); }

The Secure Implementation

The vulnerability stems from treating untrusted user input as executable SQL logic. By using template literals or string concatenation, an attacker can 'break out' of the intended string literal using single quotes and inject their own commands (e.g., UNION SELECT, OR 1=1, or DROP TABLE). The fix is the implementation of Prepared Statements (Parameterized Queries). This protocol sends the SQL template and the data to the database in two separate steps. The database engine compiles the query structure first, ensuring that the input is treated strictly as data and never as part of the command. In modern Next.js development, using type-safe ORMs like Prisma or Drizzle is the gold standard, as they abstract this protection away, but if you must write raw SQL, always use the placeholder syntax ('?' or '$1') provided by your driver.

'use server';
import { db } from '@/lib/db';
import { prisma } from '@/lib/prisma';

// SECURE: Using Parameterized Queries (Raw SQL) export async function searchUsers(query) { const sql = ‘SELECT * FROM users WHERE username = ?’; const [rows] = await db.execute(sql, [query]); return rows; }

// SECURE: Modern ORM approach (Prisma/Drizzle) export async function getPost(id) { // ORMs use parameterized queries under the hood return await prisma.posts.findUnique({ where: { id: parseInt(id) } }); }

System Alert • ID: 7987
Target: Next.js API
Potential Vulnerability

Your Next.js API might be exposed to SQL Injection (Legacy & Modern)

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