Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Security Basics  ›  Lesson

Treat Every Input as Hostile

Security Best Practices 15 minValidate every input on the server, pass it to databases only as parameters, and escape it when showing it on a page.

Treat Every Input as Hostile

The assistant added a way to edit an expense's note. Ravi changes a note to Ravi's milk, and Kitty crashes: the apostrophe broke a database query. That crash is the friendly version of the problem. The unfriendly version is someone typing a note designed to change what the query does. Anything that arrives from outside your code, such as form fields, web addresses and uploaded files, can contain anything at all.

The rule

Check input on the server, and never paste it into queries or pages.

Three habits cover most of the risk.

Keep data out of the query text. Building SQL by pasting text into it lets the text become part of the command. This is called SQL injection:

# Dangerous: the values are pasted into the SQL itself
db.execute(f"UPDATE expenses SET note = '{note}' WHERE id = {expense_id}")

# Safe: the values travel separately, as parameters
db.execute("UPDATE expenses SET note = ? WHERE id = ?", (note, expense_id))

With ? placeholders, the database treats each value purely as data, apostrophes and all. Assistants usually write the safe form, but not always, so check every query in the diff.

Escape input when you show it on a page. If Kitty inserted a note into the page as raw HTML, a note containing a <script> tag would run as code in every flatmate's browser. This is cross-site scripting. Many template systems escape text by default, turning < into harmless characters; the danger comes from code that switches that escaping off.

Validate on the server. Browser checks, such as a minimum value on a form field, help honest users but are easy to skip: anyone can send a request directly. The server must check for itself that an amount is a number, is positive, has at most two decimal places and is under the limit, and that a note is not absurdly long.

The shortcut

Follow the input. For each field, trace it from where it enters to every place it lands: the database, a page, a file, an email. At each landing spot ask one question: checked, parameterised, escaped?

Following Kitty's note fieldStep 1 of 4
  1. Where it enters

    A text box on the expense form. It can hold anything: apostrophes, HTML, ten thousand characters.

The trap is trusting the browser. If a check only exists in the form, it does not exist.

Drills

Answer fast — trust the rule.

quick drill

Which of these queries is safe from SQL injection?

quick drill

Kitty's amount field has a minimum of 0.01 set in the form. Does the server still need to check?

quick drill

A note contains a <script> tag, and Kitty inserts it into the page as raw HTML. What can happen?

quick drill

What is the shortcut for checking an input field?

Remember

  • Rule: check input on the server, and never paste it into queries or pages.
  • Shortcut: follow the input to every landing spot and ask "checked, parameterised, escaped?"
  • Trap: trusting checks that only live in the browser.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainFollow an input

Follow Kitty's amount field from the expense form, into the database and back onto the balances page. Explain the protection you would expect at each step and what could go wrong if it were missing.