Skip to content

SEC001: sql-string-building

SQL text built from values at run time

Code SEC001
Name sql-string-building
Category Security (SEC)
Default severity warning
Enabled by default yes
Fix available no
ign-lint equivalent none

Reports SQL text passed to system.db.runQuery, runUpdateQuery, runScalarQuery, runSFUpdateQuery and to the prepared-statement functions runPrepQuery, runPrepUpdate, runScalarPrepQuery and runSFPrepUpdate (and the hidden runPrepStmt, runPrepStmtGetKey, runUpdateQueryGetKey) when the text is built with %, +, .format(...) or .join(...) from values that are not literals.

The functions are recognised through imports and aliases (db = system.db, from system.db import runQuery). The query is the first argument or the query keyword. When it is a local name, every assignment that reaches the call is followed (q = "... '%s'" % name and q += ... before system.db.runQuery(q)); the finding points at the expression that builds the text.

Text built only from literals is fine: concatenated literals, module constants holding literals, placeholder lists such as ",".join(["?"] * len(ids)), and % formatting whose conversions are all numeric (%d, %i, %f, ...), which cannot carry quotes.

The prepared-statement functions are included on purpose: their ? placeholders only protect the values passed as arguments, not values pasted into the SQL text itself.

Values pasted into SQL text can change the statement (SQL injection), and quotes or special characters in ordinary data (a name such as O'Brien) break it. Prepared statements pass the values separately, and the database driver also handles types and date formats.

Table or column names chosen at run time cannot be passed as ? arguments; check them against a fixed list and suppress the finding with # iglint: ignore[SEC001] on that line.

query = "SELECT * FROM orders WHERE line = '%s'" % line
rows = system.db.runQuery(query)

Use instead:

rows = system.db.runPrepQuery("SELECT * FROM orders WHERE line = ?", [line])

Generated from the rule metadata by iglint generate-docs; iglint rule SEC001 prints the same page in the terminal. Source: docs/rules/SEC001.md.