Parameterized Queries
Parameterized queries (prepared statements) are the primary defense against SQL injection. They separate SQL code from data, making injection structurally impossible regardless of what the user inputs:
// JavaScript (node-postgres)
const result = await pool.query(
'SELECT * FROM users WHERE id = $1', [userId]
);
# Python (psycopg2)
cursor.execute(
"SELECT * FROM users WHERE id = %s", (user_id,)
)
// Java (JDBC PreparedStatement)
PreparedStatement stmt = conn.prepareStatement(
"SELECT * FROM users WHERE id = ?"
);
stmt.setInt(1, userId);
// Go (database/sql)
row := db.QueryRow(
"SELECT * FROM users WHERE id = $1", userID
)
The database driver sends the query template and parameters separately. The database compiles the template first, then binds the parameters as data—never as executable SQL.
ORM Best Practices
ORMs like Sequelize, SQLAlchemy, Hibernate, and GORM generate parameterized queries by default. The risk reappears when developers use ORM escape hatches:
- Sequelize:
sequelize.query(userInput)bypasses parameterization - SQLAlchemy:
db.engine.execute(f"SELECT * FROM users WHERE id = {uid}") - Hibernate:
session.createQuery("FROM User WHERE name = '" + name + "'") - Django:
Model.objects.raw(user_controlled_query)
When raw queries are necessary, always use the ORM's parameterized raw query interface instead of string concatenation.
Automated Detection with SAST
Manual code review cannot cover every code path in a growing codebase. Static Application Security Testing (SAST) tools scan source code automatically to find SQL injection patterns before they reach production.
Effective SAST for SQL injection detection should identify:
- String concatenation and template literals in SQL query construction
- ORM raw query methods with unparameterized input
- Missing placeholder parameters in database queries
- Dynamic query builders with user-controlled variables
Integrating SAST into CI/CD pipelines ensures every pull request and pre-commit is checked for SQL injection patterns, catching vulnerabilities that slip through manual review.
How CodeSlick Prevents SQL Injection
CodeSlick detects SQL injection across JavaScript, TypeScript, Python, Java, and Go with checks that target the specific patterns attackers exploit:
- String concatenation and template literals in SQL statements
- ORM escape hatches:
sequelize.query(),knex.raw(),cursor.execute()with format strings,Statement.execute() - Missing parameterization in all five supported languages
CodeSlick runs on every pull request via the GitHub App, on every commit via the CLI pre-commit hook, and on-demand in the free web scanner. All findings include CWE-89 mapping, CVSS scoring, and AI-powered fix suggestions that generate parameterized alternatives.
Automatically detect SQL injection patterns in every pull request and pre-commit.