Change Data Safely
Keep SQL-Looking Text as Data
An asset tag is allowed to contain an apostrophe. It may even contain text that resembles SQL. Your find_item
Consider this exact call:
find_item(connection, "X' OR 1=1 --")
The value looks unusual, but the function still uses the same statement and one-item
| Part | What reaches SQLite |
|---|---|
| SQL statement | WHERE asset_tag = ? |
| Separate values | ("X' OR 1=1 --",) |
| Result | None |
| Item count afterward | unchanged |
SQLite treats every character inside the bound value as data for the one ? position. The apostrophe, spaces, equals sign, and dashes do not become SQL structure. No stored tag matches the complete value, so the search returns None.
The unsafe boundary appears when a program builds statement text from a changing value. An
statement = f"... WHERE asset_tag = '{asset_tag}'"
Here the value is inserted into the statement before SQLite reads it. An apostrophe can close the quoted value early, and the remaining characters can be interpreted as SQL. User-controlled text changing a statement’s structure is an SQL injection risk.
Here is that safe boundary as one complete call:
connection.execute(
"SELECT id FROM items WHERE asset_tag = ?",
(asset_tag,),
)
Placeholders are not a general substitution system. A ? can stand where SQL expects a value, such as an asset tag or loan period. It cannot stand for a table name, column name,
Which call keeps the changing asset tag as data while leaving the SQL structure fixed?
The safe rule is pleasantly small: keep SQL fixed, keep changing values complete, and pass those values separately.