The single most important rule
Never build SQL by string concatenation or f-strings with user input. Use placeholders and pass parameters separately. The driver handles escaping; SQL injection becomes impossible by construction.
SQLite supports two placeholder styles:
- Qmark:
?with a tuple/list. Order-based. - Named:
:namewith a dict. Self-documenting.
Warning:
conn.execute(f'SELECT * FROM users WHERE name = "{name}"') is a security bug. The same pattern in production has been the root cause of countless data breaches. Use placeholders, always — even for 'trusted' input. Trusted is a slippery property.The one thing placeholders cannot parameterize is identifiers (table names, column names). For those, validate against an allowlist and only then format into the SQL string.