| name | detecting-sql-injection-patterns |
| description | Scan a source tree for SQL-injection vulnerable patterns: string
concatenation into queries, f-string interpolation in SQL,
string-format substitution into raw queries, deprecated cursor
methods (cursor.execute with % formatting), Knex / Sequelize raw()
with template interpolation, sequelize.query with replacements.
Use when: pre-commit code review, post-feature SQL-touching
release, inheriting a legacy codebase that predates ORMs, or
post-bug-report investigation.
Threshold: any source line where SQL keywords (SELECT / INSERT /
UPDATE / DELETE / FROM / WHERE) appear in a string that's being
built via concatenation, f-string, %-format, or .format() with
variable input.
Trigger with: "scan for sqli", "sql injection patterns",
"check raw queries", "audit cursor.execute".
|
| allowed-tools | ["Read","Bash(python3:*)","Glob","Grep"] |
| disallowed-tools | ["Bash(rm:*)","Bash(curl:*)"] |
| version | 3.30.0 |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
| license | MIT |
| compatibility | Designed for Claude Code |
| tags | ["security","static-analysis","sql-injection","pentest"] |
Detecting SQL Injection Patterns
Overview
SQL injection (CWE-89, OWASP A03:2021) remains one of the highest-
impact and most-easily-introduced vulnerability classes. The fix is
near-universal: use parameterized queries. The cause when introduced:
an engineer concatenates user input into a SQL string because the
ORM's parameterization mechanism wasn't obvious, or because they
"just need to add a quick condition."
The scanner reads source files and grades each apparent SQL-string
construction against the threshold table.
When the skill produces findings
| Finding | Severity | Threshold | Affected control |
|---|
| f-string with SQL keywords + user input | CRITICAL | f"SELECT * FROM users WHERE id = {user_id}" | CWE-89 |
| String concat into SQL keyword string | CRITICAL | "SELECT ... " + var + " ..." | CWE-89 |
| %-format SQL string | HIGH | "SELECT * FROM %s" % table_name | CWE-89 |
.format() into SQL string | HIGH | "SELECT {} FROM users".format(col) | CWE-89 |
cursor.execute(f"...") | CRITICAL | f-string passed directly to cursor.execute | CWE-89 |
sequelize.query with template literal | HIGH | sequelize.query(\SELECT * FROM ${table}`)` | CWE-89 |
| Knex / sequelize raw() with interpolation | HIGH | knex.raw('SELECT * FROM ' + table) | CWE-89 |
Django .extra() with raw SQL | MEDIUM | Model.objects.extra(where=['col = ' + val]) | CWE-89 |
cursor.executemany with string-built query | CRITICAL | Same risk as execute | CWE-89 |
JDBC Statement.execute with concat |