Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
Salesforce Developer
hard

How do you prevent SOQL injection in Apex?

SOQL Injection is when user input gets concatenated into a SOQL query, allowing the user to manipulate the query structure. Like SQL injection but for Salesforce.

Vulnerable code:

public List<Account> findByIndustry(String userInput) {
    String query = 'SELECT Id, Name FROM Account WHERE Industry = \'' + userInput + '\'';
    return Database.query(query);
}

If userInput is ' OR Name LIKE '% — the query becomes WHERE Industry = '' OR Name LIKE '%' — returns all accounts.

Safe patterns:

1. Bind variables (always preferred):

public List<Account> findByIndustry(String userInput) {
    return [SELECT Id, Name FROM Account WHERE Industry = :userInput];
}

Salesforce parameterises bind variables; injection is impossible.

2. Bind variables in dynamic SOQL:

String safeIndustry = userInput; // bound below
String query = 'SELECT Id FROM Account WHERE Industry = :safeIndustry';
List<Account> accs = Database.query(query);

The : prefix in dynamic SOQL is parameterised the same way.

3. `String.escapeSingleQuotes` for cases where bind variables can't work:

String escaped = String.escapeSingleQuotes(userInput);
String query = 'SELECT Id FROM Account WHERE Name LIKE \'%' + escaped + '%\'';

Escapes single quotes within the string. Less robust than bind variables; use only for legitimate cases like wildcard concatenation.

4. Whitelist for object/field names (which can't be bind-variable):

Set<String> allowedObjects = new Set<String>{'Account', 'Contact', 'Opportunity'};
if (!allowedObjects.contains(userInput)) throw new IllegalArgumentException();
String query = 'SELECT Id FROM ' + userInput;

5. `Schema.SObjectType.validate(input)` patterns — validate against the org's known objects and fields before composing queries.

Rules of thumb:

  • Never concatenate raw user input into a SOQL query string.
  • Bind variables for values; whitelist for identifiers (object/field names).
  • Don't trust client-side validation — validate again in Apex.
  • Audit `Database.query` and `Database.queryWithBinds` usages — these are the injection surfaces.

Beyond SOQL: similar principles apply to dynamic SOSL, dynamic DML, and dynamic Visualforce/LWC component instantiation. Anywhere user input meets a runtime parser, sanitisation matters.

Tooling: PMD has SOQL-injection detection rules. Run static analysis as part of CI.

Why this answer works

Senior security. The bind-variable rule, escapeSingleQuotes, and whitelist patterns together are comprehensive. Mentioning PMD signals tooling maturity.

Follow-ups to expect

Related dictionary terms