Two traps: building SQL with f-strings, and forgetting PRAGMA foreign_keys = ON.
Goal
Print the injection string, then show FK off vs on.
city = "x' OR '1'='1"
print("unsafe", f"SELECT * FROM t WHERE city = '{city}'")import sqlite3
con = sqlite3.connect(":memory:")
con.execute("CREATE TABLE t (city TEXT)")
con.execute("INSERT INTO t VALUES ('Nairobi')")
city = "Nairobi"
print(con.execute("SELECT * FROM t WHERE city = ?", (city,)).fetchall())
con.close()import sqlite3
con = sqlite3.connect(":memory:")
print("fk default", con.execute("PRAGMA foreign_keys").fetchone())
con.execute("PRAGMA foreign_keys = ON")
print("fk on", con.execute("PRAGMA foreign_keys").fetchone())
con.close()import sqlite3
con = sqlite3.connect(":memory:")
con.execute("CREATE TABLE t (n INTEGER PRIMARY KEY)")
try:
con.execute("INSERT INTO t VALUES (1)")
con.execute("INSERT INTO t VALUES (1)")
except sqlite3.IntegrityError as err:
print(err)
con.close()