ESLint InterlaceESLint Interlace
Plugin: pgRules

no-unsafe-query

ESLint rule documentation for no-unsafe-query

📡 Live from GitHub — This documentation is fetched directly from no-unsafe-query.md and cached for 6 hours.

Prevents SQL injection by detecting string concatenation or template literals with variables in client.query() calls.

SQL injection is one of the most critical security vulnerabilities

🚨 Security rule | 💡 Provides LLM-optimized guidance | ⚠️ Set to error in recommended

Quick Summary

AspectDetails
CWE ReferenceCWE-89 (SQL Injection)
SeverityCritical (CVSS: 9.8)
Auto-Fix❌ No auto-fix available
CategorySecurity
ESLint MCP✅ Optimized for AI assistant integration
Best ForProtecting database operations from SQL injection vulnerabilities

Rule Details

SQL injection is one of the most critical security vulnerabilities. This rule detects potentially unsafe SQL query construction in pg driver calls.

❌ Incorrect

// Template literal with variable
const result = await client.query(`SELECT * FROM users WHERE id = ${userId}`);

// String concatenation
const query = "SELECT * FROM users WHERE name = '" + userName + "'";
await pool.query(query);

✅ Correct

// Parameterized query
const result = await client.query('SELECT * FROM users WHERE id = $1', [
  userId,
]);

// Named parameters (with pg-named or similar)
const result = await client.query({
  text: 'SELECT * FROM users WHERE id = $1',
  values: [userId],
});

Error Message Format

The rule provides LLM-optimized error messages (Compact 2-line format) with actionable security guidance:

🔒 CWE-89 OWASP:A05 CVSS:9.8 | SQL Injection detected | CRITICAL [SOC2,PCI-DSS,HIPAA,ISO27001]
   Fix: Review and apply the recommended fix | https://owasp.org/Top10/A05_2021/

Message Components

ComponentPurposeExample
Risk StandardsSecurity benchmarksCWE-89 OWASP:A05 CVSS:9.8
Issue DescriptionSpecific vulnerabilitySQL Injection detected
Severity & ComplianceImpact assessmentCRITICAL [SOC2,PCI-DSS,HIPAA,ISO27001]
Fix InstructionActionable remediationFollow the remediation steps below
Technical TruthOfficial referenceOWASP Top 10

Known False Negatives

The following patterns are not detected due to static analysis limitations:

Tagged Template Literals (sql...)

Why: Tagged templates like sql from libraries are function calls, not template literals.

// ❌ NOT DETECTED - appears safe but may not be
import { sql } from 'some-library';
await client.query(sql`SELECT * FROM users WHERE id = ${userId}`);
// If 'sql' doesn't properly escape, this is vulnerable!

Mitigation: Use a library verified to properly escape tagged templates.

Dynamic Query Variables

Why: When the query is stored in a variable, we can't analyze its construction.

// ❌ NOT DETECTED
const unsafeQuery = buildQuery(userInput); // May concatenate strings internally
await client.query(unsafeQuery);

Mitigation: Always use parameterized queries ($1, $2) directly in literals.

Nested Function Calls

Why: Queries passed through helper functions aren't traced.

// ❌ NOT DETECTED
function executeQuery(query: string) {
  return client.query(query);
}
executeQuery(`SELECT * FROM users WHERE id = ${userId}`);

Mitigation: Apply the rule to helper functions that execute queries.

Format Functions with User Input

Why: The rule doesn't track data flow through pg-format or similar.

// ❌ NOT DETECTED - but format() should handle escaping
import format from 'pg-format';
await client.query(format('SELECT * FROM %I.users', userSchema));
// Safe if format() escapes, but rule can't verify

Mitigation: Use parameterized queries for values; use verified formatters only for identifiers.

When Not To Use It

  • When using a query builder (Drizzle, Kysely) that handles parameterization
  • In migration files with static SQL

On this page

No Headings