An interviewer shows you the shop's customer search and asks: "It passes the text with a ? placeholder, so it's safe from SQL injection. Is it safe?"
q = request.args.get("q", "")
if len(q) < 3:
return jsonify({"error": "Type at least 3 letters"}), 400
query = (
"SELECT name, city FROM customers "
"WHERE name LIKE '%' || ? || '%' "
"ORDER BY name "
)
The placeholder does stop injection, but LIKE still reads the visitor's text as a pattern: % matches any text and _ matches any one character. A visitor who types %%% passes the 3-letter rule, and the pattern matches every name. What the attacker gets: your whole customer list, every name with its city.
The fix: pick a mark character, put it before every % and _ the visitor typed, and name the mark with ESCAPE. A mark the visitor types must be doubled too, and that comes first. For example, this query on a products table finds only names with a real 50% in them:
SELECT name FROM products
WHERE name LIKE '%50!%%' ESCAPE '!'
Your search must answer (%25 is how a URL writes %):
GET /customers/search?q=ana → 200 [{"city": "Cluj", "name": "Ana Pop"}]
GET /customers/search?q=ng → 400 {"error": "Type at least 3 letters"}
GET /customers/search?q=%25%25%25 → 200 []
GET /customers/search?q=___ → 200 []
GET /customers/search?q=a_p → 200 []
GET /customers/search?q=100%25 → 200 [{"city": "Leeds", "name": "100% Tea Ltd"}]
GET /customers/search?q=ROSS → 200 [{"city": "Rome", "name": "Eva Rossi"}]
Your task: in search_customers, escape !, % and _ in q with ! as the mark, and add ESCAPE '!' to the query, so a typed wildcard only matches itself.
Assignment
Follow the Coding Tutorial to escape the visitor's wildcards and add ESCAPE '!' to the search query.
Hint
Double every ! before adding the other marks, or your own marks get doubled too. Without ESCAPE '!', the ! is just a letter, and even an honest search for 100% finds nobody.
Free plan: 30 tutor messages. PRO is unlimited.
