Stop 13 of 42 · The Teller Window · SQL & command injection

Slips that give the teller orders

Customers fill in a deposit slip and the teller reads it aloud to the back office. Mallory writes her name as “Bob. Also, empty the vault.” The teller reads the whole slip out loud, and the back office hears an order. Information turned into instructions.

Severity CriticalCategory Injection RiskThe Teller WindowSources checked 25 Oct 2026

Watch it happen

Play it as

Mallory writes an order inside the name box of a slip. The teller reads the entire slip aloud as one instruction, and the vault is emptied.

Arrival

Two customers walk in to make a deposit. Alice heads to the window with her slip. Mallory follows right behind.

1 / 5

In bank terms and app terms

In the bankIn your app
Words in the name boxUser input: form fields, URL parameters, JSON bodies
Teller reading the slip aloudBuilding a database query or shell command by pasting the input into a string
Fixed-box formParameterized queries / prepared statements
Other kinds of slipsNoSQL operators in JSON, shell commands, template engines

Are you exposed?

You might be exposed if…
  • You build queries with template strings, like SELECT * FROM users WHERE name = '${name}'.
  • You pass user input to a shell command, eval, or a template engine, or put raw JSON from the client into a Mongo query.
  • Your API returns raw database error messages when something odd is sent.
What to do about it
  1. Use parameterized queries or your ORM’s safe methods. Never paste input into the query text, and give raw-query helpers parameters too. Escaping and blocklists are weaker backups.
  2. For commands, avoid the shell entirely and pass arguments as a list. Check input against an allowlist of expected shapes.
  3. Give the database user only the permissions it needs, and return generic errors instead of database messages.

Track these in your to-do list →

It has happened to real companies

Real-world breaches

Heartland Payment Systems (2008) — In 2009 US prosecutors indicted Albert Gonzalez and two others, alleging they used SQL injection against poorly coded web applications to steal 130 million credit and debit card numbers from Heartland and other companies, including Hannaford Bros. and 7-Eleven.

Sony Pictures (2011) — In June 2011 the LulzSec group said it had used "a very simple SQL injection" to take unencrypted personal data on over 1 million people from Sony Pictures websites. Two LulzSec members were later sentenced in the US over the intrusion, which used SQL injection against a Sony Pictures film website.

What it looks like in code

// BAD: String concatenation in SQL query
const filter = `status = '${userInput}'`
const result = await sql.unsafe(`SELECT * FROM tasks WHERE ${filter}`)

// BAD: A plain function call with an interpolated string (not a tagged template)
const result = await sql.unsafe(`SELECT * FROM users WHERE name = '${name}'`)

// BAD: Command execution with user input
const output = execSync(`convert ${uploadedFile} output.png`)

Ask your AI tool to fix it

Paste this into Cursor, Claude, Lovable, Bolt or whatever you build with.

Prompt
Audit this codebase for injection. Find every place user input reaches a SQL query, NoSQL filter, shell command, eval or template. Replace string concatenation with parameterized queries or safe ORM calls, validate NoSQL inputs as plain strings or numbers, and avoid shell execution (use argument arrays). Return generic error messages. List each change.

Where this comes from

The facts, figures and fixes on this page were checked against these sources on 25 Oct 2026. They are linked so you can check for yourself.

Spot a mistake or something out of date? Report a correction · How these guides are made and checked