Skip to main content
interlace
Plugin: drizzle-securityRules

no-unsafe-query

Prevent SQL injection by disallowing string concatenation or interpolated template literals in Drizzle sql.raw() calls.

CWE: CWE-89 OWASP: A03:2021 – Injection

Detects SQL injection in Drizzle raw queries. This rule is part of eslint-plugin-drizzle-security.

💼 This rule is set to error in the recommended config.

Quick Summary

AspectDetails
CWE ReferenceCWE-89 (SQL Injection)
SeverityCritical (CVSS 9.8)
Auto-Fix❌ No auto-fix available
CategorySecurity

Rule Details

Reports three shapes when they reach a raw-SQL sink:

  1. String concatenation — sql.raw('SELECT ... ' + value)
  2. Template interpolation — sql.raw(`SELECT ... ${value}`)
  3. A variable tainted by either, including via +=, then passed to a sink

Sinks

sql.raw() only. The safe sql tagged template parameterizes its interpolations and is a different AST node, so it can never be reported.

❌ Incorrect

await sql.raw(`SELECT * FROM users WHERE id = ${userId}`);

await sql.raw('SELECT * FROM users WHERE email = ' + email);

let sql = 'SELECT * FROM products WHERE 1=1';
sql += ` AND name = '${name}'`;
await sql.raw(sql);

✅ Correct

db.select().from(users).where(sql`id = ${userId}`);

Known limitations

  • Only identifier member access is matched, so sql['raw'](...) is a false negative.
  • Taint tracking is single-scope and name-based — it does not follow a query string across function boundaries.

Implementation

The detection is shared across the driver plugins via createSqlInjectionRule in @interlace/eslint-devkit; this rule supplies Drizzle's sinks and remediation copy. Install the plugin matching your stack and you get exactly one finding per line.

Further Reading

Did this rule catch something? Star the repo to get new CWE coverage as we ship it — or follow the AI-code-security benchmarks behind these rules.