Advanced 30 min read

SOQL Injection

By the end of this lesson, you'll be able to:

  • Recognize a SOQL injection vulnerability in dynamic SOQL
  • Apply bind variables and escapeSingleQuotes() as the two core defenses
  • Explain why this deserves a full lesson beyond Module 20's introduction

Prerequisites: "User Mode Database Operations"

A recap, viewed through a security lens

// DANGEROUS
String userInput = someFormField;
String queryString = 'SELECT Id FROM Account WHERE Name = \'' + userInput + '\'';
List<Account> accounts = Database.query(queryString);

Module 20 introduced this exact danger — concatenating raw user input directly into a dynamic query string lets a carefully crafted input alter the query's actual structure, potentially exposing or affecting data the input was never meant to touch.

Defense 1: bind variables (the default choice)

String userInput = someFormField;
List<Account> accounts = Database.query('SELECT Id FROM Account WHERE Name = :userInput');

Exactly Module 20's recommendation, restated as this module's primary defense: a bind variable never mixes raw input with the query's syntax at all, which is why it's the preferred fix whenever the query's overall structure doesn't need to change based on user input — just a value being filtered on.

Defense 2: escaping, when structure genuinely must vary

String fieldName = getFieldNameFromConfig(); // the field itself varies, not just a value
String safeFieldName = String.escapeSingleQuotes(fieldName);
String queryString = 'SELECT Id FROM Account WHERE ' + safeFieldName + ' != null';

Bind variables can only stand in for values, not query structure like field or object names — when a genuinely dynamic field name must be concatenated directly, String.escapeSingleQuotes() neutralizes quote characters that could otherwise let an input break out of the intended structure. This is a narrower, last-resort tool compared to bind variables, not a general substitute for them.

Why this earns a dedicated security-module lesson

Module 20 introduced SOQL injection as one lesson among many on writing correct SOQL; this security module revisits it specifically as a security vulnerability class, alongside CRUD/FLS and sharing — the same underlying risk, but now framed as something to actively defend against as a matter of course, on every dynamic query written, not just something to remember once.

Exercise

Rewrite this dynamic query to use a bind variable instead of string concatenation.

Show hint

Replace the concatenated value with :searchTerm.

APEX

SOQL Injection Quiz

1. What can a bind variable stand in for, versus what String.escapeSingleQuotes() is needed for?

Log in to submit the quiz and save your score.

My Notes

Log in to keep private notes on this lesson.

Questions about this lesson

No questions yet — be the first to ask.

Log in to ask a question about this lesson.

Summary

This lesson revisits Module 20's SOQL injection introduction with a security-module's depth — the full picture of how it happens and how to defend against it consistently.