In this lesson, you will learn how to secure your database applications by using query parameterization to neutralize malicious user input before it ever reaches the database engine.
The Problem: SQL Injection
When building applications for embedded databases, it is tempting to build queries by concatenating strings. For example, if you have a user-provided username, you might write:
-- DANGEROUS: Do not do this!
query = "SELECT * FROM users WHERE username = '" + user_input + "';"
If a malicious user enters ' OR '1'='1 as their username, the resulting query becomes SELECT * FROM users WHERE username = '' OR '1'='1';. This bypasses your security logic entirely, allowing unauthorized access. This is known as SQL Injection.
The Solution: Query Parameterization
Instead of embedding raw data into the SQL string, query parameterization keeps the logic (the command) and the data (the input) separate. You use placeholders—typically ? or named parameters like :name—within your SQL statement.
When you execute the query, you pass the input data as a separate argument. The database engine receives the command structure first, ensuring it knows exactly what the query is supposed to do. Then, it treats the provided data strictly as a literal value, never as part of the executable command.
Here is how a secure routine looks in practice:
# SECURE: Using parameterization
cursor.execute("SELECT * FROM users WHERE username = ?", (user_input,))
By using this approach, if the user tries to input ' OR '1'='1, the database will simply look for a user whose literal name is the string "' OR '1'='1". It will not execute the injected logic because the input is safely "quoted" or bound by the driver.
Why This Matters for Embedded Systems
Even though embedded databases like SQLite often run locally, they frequently handle sensitive data or configuration files. Using parameterized queries is a defensive programming habit that protects your application from unexpected data handling issues, regardless of whether the threat comes from a malicious user or simply malformed input that could crash your query parser.
Key Takeaway: Never concatenate user input into your SQL strings; always use placeholders to strictly separate your executable code from your data values.