Sql injection defense
Skill Amey-Thakur/AI-SKILLS/skills/security/sql-injection-defense
Plug-and-play skills and prompts for every AI coding agent
npx -y skills add Amey-Thakur/AI-SKILLS --skill sql-injection-defenseAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 19 days oldThe repository was created 19 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Eliminate SQL injection by sending data as bound parameters instead of concatenated query text, and auditing every raw-SQL escape hatch. Use when writing or reviewing code that builds database queries from variables.
SKILL.md
2.8 KB, as published. Nobody here has run it
SQL injection defense
SQL injection persists because building a query with string concatenation feels natural and works in every demo. The fix is not smarter escaping: it is refusing to put data in the query string at all. Send the query and the data on separate channels and the whole class disappears.
Method
- Use parameterized queries for every value, always. Write
WHERE email = ?orWHERE email = %s/:emailand pass the value as a bound parameter. The driver sends SQL and data separately, so input can never change the query's structure. This is the entire defense; the rest is enforcing it. - Never concatenate or interpolate user data into SQL.
f"... WHERE id = {id}","... = '" + name + "'", and template literals into a query are the bug. Ban them in review. Manual escaping and quoting are not a substitute: you will miss a code path or an encoding. - Parameterize through the ORM, and audit its escape hatches. Prefer
the query builder (
User.objects.filter(email=x),session.query(...).filter(User.email == x)). Then grep the raw doors:.raw(,execute(,text(,.extra(,sequelize.query,knex.raw. Each raw call must still bind parameters, not format a string. - Parameterize identifiers differently from values. Placeholders bind
values, not table or column names or
ASC/DESC. When a column or sort direction comes from input, match it against a hardcoded allowlist of legal names; never interpolate it raw. - Grant the app database account least privilege. The runtime user
needs
SELECT/INSERT/UPDATE/DELETEon its own tables, notDROP,GRANT, or other schemas. Least privilege caps the blast radius when a query is compromised through some other flaw. - Add a lint gate against string-built SQL. Turn on a rule (Bandit B608, a Semgrep sql-injection pattern, CodeQL) in CI that flags formatted query strings. A rule catches the regression a reviewer skims past at 5 p.m.
Litmus tests
- Does every query send user data as a bound parameter, with zero values in the SQL text?
- Have you grepped for raw-query methods and confirmed each still binds?
- Are dynamic column and sort inputs checked against an allowlist rather than interpolated?
Boundaries
This skill covers relational SQL. NoSQL query injection (MongoDB $where,
JSON operators) follows the same principle with different mechanics. Stored
procedures help only if they use parameters internally; dynamic SQL built
inside a procedure is just as vulnerable.