SQL remains parameterized and structural query fragments are allowlisted
sec-003
Intent
Keep untrusted data out of query structure so values remain data and structural fragments stay under explicit developer control.
Applicability
Applies when the diff adds or changes raw SQL, native queries, stored procedure calls, or query fragments such as ORDER BY or selected columns. Return unknown when final query rendering is hidden behind abstractions.
What to inspect
SQL strings, ORM raw-query APIs, string interpolation, placeholders, parameter bags, and dynamic identifier mapping.
Pass criteria
Values are bound separately from query text, and any dynamic identifiers or sort directions are mapped from a closed allowlist.
Fail criteria
External values are concatenated or interpolated into SQL text, or user input directly selects structural fragments without an explicit allowlist.
Do not flag
Constant migration SQL. ORM query builders that parameterize safely. Closed enum-to-identifier mappings visible in the repository.
Confidence guidance
HIGH when direct interpolation is visible. MEDIUM when dynamic composition exists but trust level is inferred. LOW when final query generation is hidden.
Remediation
Use parameter binding for values and fixed allowlists for structural query choices.
Pass example
cursor.execute("SELECT * FROM users WHERE email = %s", [email])
Fail example
cursor.execute(f"SELECT * FROM users WHERE email = '{email}' ORDER BY {sort}")