Module 59: SQLite

Lesson 3 of 5 · 15–25 minutes

Parameterised queries and SQL injection

🏠The everyday picture

A bank form has boxes: "Pay ₹____ to ____". Whatever someone writes in the box is treated as an amount or a name, never as a new instruction to the bank. If the clerk instead copied the customer's words straight into the bank's instruction book, "₹10, and also close everyone else's accounts" would be obeyed.

📘What it really is

// NEVER do this
db.prepare(`SELECT * FROM customers WHERE name = '${req.query.name}'`).all();

If someone sends the name x' OR '1'='1, the query returns every customer. Cleverer input can read other tables or delete data. It has been one of the most damaging security flaws for decades.

db.prepare("SELECT * FROM customers WHERE name = ?").all(req.query.name);
db.prepare("INSERT INTO customers (name, phone, city) VALUES (@name, @phone, @city)").run(input);
const sortColumns = { name: "name", joined: "joined_on" } as const;
const column = sortColumns[query.sort] ?? "name";

🖱️Try it

Write a deliberately unsafe search function in a scratch file and show that the input x' OR '1'='1 returns every customer. Then rewrite it with a placeholder and show the same input returns nothing. Add a sorted list function that uses an allow-list for the sort column.

✅Quick check

What makes a query vulnerable to SQL injection?

Show the answer

Joining user input directly into the SQL text, so it can change the query's meaning.

Can a column name for sorting be passed as a ? parameter?

Show the answer

No. Parameters are for values; choose column names from an allow-list in code.

← PreviousConnecting from Node.js
ProLearners Assist