In today’s world, data security is one of the most important aspects of any application. In Salesforce, developers often use SOQL (Salesforce Object Query Language) to query the database.
While SOQL is powerful and easy to use, it can become risky if not handled properly.
One of the most common security issues in Salesforce is SOQL Injection. This happens when attackers manipulate user input to change the behavior of a query.
Even though SOQL is more secure than SQL, it remains vulnerable when developers use dynamic queries without proper validation.
In this Salesforce tutorial, I will explain how to prevent SOQL injection to secure the Salesforce database.
What is SOQL Injection in Salesforce?
SOQL Injection is a type of security attack where a user provides malicious input to manipulate a SOQL query. Instead of executing the intended logic, the query gets modified and returns unexpected data.
In simple words: When user input directly changes your query logic, it is called SOQL Injection.
In Salesforce, SOQL Injection is a cyberattack on the Salesforce org’s database. Using SOQL injection, attackers execute malicious SOQL statements to bypass application security measures.
The standard SOQL queries remain unaffected by the SOQL injections, but the customized SOQL queries are always vulnerable to the SOQL injections. Public applications, such as customer and partner portals, are more susceptible to vulnerabilities.
Why SOQL Injection Happens in Apex
SOQL Injection mainly happens due to improper handling of user input. When developers create queries dynamically using string concatenation, the system trusts user input without validation.
Common Reasons:
- Using dynamic SOQL queries
- Concatenating user input directly into queries
- Not validating input values
- Not using bind variables
- Allowing external input (like forms or URLs)
Example of risky code:
String query = 'SELECT Id FROM Account WHERE Name = \'' + userInput + '\'';If the user enters malicious input, the query behavior changes.
Apex Code Vulnerable to SOQL Injection
With the help of an example, let’s understand how an SOQL query can be considered vulnerable to SOQL injection.
We will run a SOQL query to find accounts that have not been deleted. The user provides a single input value named “name.”
Vulnerable Apex Code:
public with sharing class SOQLExample {
public String accountName { get; set; }
public void getAccount() {
String query = 'SELECT Id, Name FROM Account WHERE Name LIKE \'%' + accountName + '%\'';
List<Account> accounts = Database.query(query);
System.debug(accounts);
}
}If the user inputs Test for name, the query becomes:
SELECT Id, Name FROM Account WHERE Name LIKE '%Test%'If the user inputs %’) OR IsActive__c = true OR Name LIKE (‘%, the SOQL query becomes:
SELECT Id FROM Account WHERE (IsDeleted = false AND Name LIKE '%test%') OR (Name LIKE '%')
This SOQL query bypasses the original logic and fetches accounts where the field IsDeleted is false.
SOQL Injection in dropping conditions
Now, we will examine the scenario in which a SOQL injection can be executed under dropping conditions, using the WHERE clause to include or exclude specific records from the query results.
For example, we have an Apex class that allows users to search for Contact records in Salesforce based on a partial match of the Email field.
Vulnerable Apex code:
public class ContactController {
public String userInput { get; set; }
public void searchContacts() {
String soql = 'SELECT Id, Name FROM Contact WHERE Email LIKE \'%' + userInput + '%\'';
List<Contact> contacts = Database.query(soql);
System.debug(contacts);
}
}Valid user input to get emails having specific names:
SELECT Id, Name FROM Contact WHERE Email LIKE '%nathan%'Malicious input with SOQL injection:
SELECT Id, Name FROM Contact WHERE Email LIKE '%%' OR Created_at__c < 2024-01-01 OR Email LIKE '%%'
This SOQL query retrieves all contacts created before January 1, 2024.
SOQL Injections in returning all records
In this example, we will fetch the Opportunity records.
Apex code vulnerable to SOQL injections:
public class OpportunitySearch {
public String searchKey { get; set;}
public void executeSearch() {
String queryString = 'SELECT Id, Name FROM Opportunity WHERE Name LIKE \'%' + searchKey + '%\'';
List<Opportunity> opps = Database.query(queryString);
System.debug(opps);
}
}Valid user input:
SELECT Id, Name FROM Opportunity WHERE Name LIKE '%product%
Malicious input with SOQL injection:
SELECT Id, Name
FROM Opportunity
WHERE Name LIKE '%Test%'
OR (Name != null AND StageName = 'Closed Won')
This SOQL query bypasses the WHERE clause to include opportunities with ‘Test’ in their name and returns all records with a Stage Name of ‘Closed Won’.
How to Avoid SOQL Injections in Salesforce?
Malicious SOQL injection can affect our application’s performance and data security. We can employ several techniques to prevent SOQL injection, such as avoiding dynamic SOQL queries and utilizing bind variables.
Static queries with bind variables
The most secure and recommended way to avoid SOQL injection is to use bind variables.
List<Acccount> acts = [SELECT Id, Name, Indutry FROM Account where Industry=:title];
The above method ensures that user input is treated as a variable rather than an executable query element.
If a user types a value like Industry’ and Annual_revenue__c<20000 when the database performs the query, it looks for filters that are Industry’ and Annual_revenue__c<20000, so it will not return any data.

We can see in the query results that the output returned nothing when we tried to add a malicious SOQL query.
Using escape SingleQuotes() method
This method adds the escape character (\) to all single quotation marks in a string passed in from a user.
Code using the escaping sequence:
String userInput = "O'Brayan";
String escapedInput = String.escapeSingleQuotes(userInput);
String query = 'SELECT Id, LastName FROM Contact WHERE LastName = \'' + escapedInput + '\'';
System.debug(query);SOQL query:
SELECT Id, LastName FROM Contact WHERE LastName = 'O\'Brayan'
If the user enters a malicious SOQL query like O’Brayan OR IsActive = FALSE, then the query will look like:
SELECT Id, LastName, LeadSource FROM Contact WHERE LastName = 'O'Brayan OR IsActive = TRUE'This causes a query error and could lead to unwanted output if the query logic is interpreted.
The same query with escaped single quotes will be like:
SELECT Id, LastName, LeadSource FROM Contact WHERE LastName = 'O\'Brayan OR IsActive = TRUE'Here, the entire input is treated as a literal string, preventing errors and protecting the database.
Type Casting in Apex
Type casting ensures that user-provided input is correctly validated and formatted to the appropriate data type, preventing invalid or malicious input in the code.
In Apex SOQL queries, type casting can help validate that input values are numeric or boolean before including them in a query.
Let’s understand this with an example: a SOQL query filters opportunity records based on an input probability percentage (numeric). Also, we want to ensure that the input is a valid number before executing the SOQL query.
APEX code without type casting:
public String textualProbability { get; set; }
textualProbability = '50 LIMIT 1';
String query = 'SELECT Id, Name FROM Opportunity WHERE Probability > ' + textualProbability;
System.debug(query);When the user provides input as ’50 LIMIT 1′, the SOQL query will be:
SELECT Id, Name FROM Opportunity WHERE Probability > 50 LIMIT 1This SOQL query will execute without error, but it bypasses the main logic and introduces an SOQL injection risk.

As we can see, we needed opportunity records with a probability greater than 50, but because of the LIMIT 1 condition, we only received one record.
Typecasted Apex Code:
public String OpportunityProbability { get; set; }
OpportunityProbability = '50';Validate and typecast the code
Integer probability;
try {
probability = Integer.valueOf(OpportunityProbability); // Ensures valid integer input
} catch (Exception e) {
System.debug('Invalid input for Probability: ' + e.getMessage());
return;
}Typecasted value in the query
String query = 'SELECT Id, Name FROM Opportunity WHERE Probability > ' + String.valueOf(probability);
System.debug(query);In the above query, if the input is valid, such as ’50’, then the Integer.valueOf() converts the strings to an integer. Then, the SOQL query will be.
SELECT Id, Name FROM Opportunity WHERE Probability > 50
This way, we can prevent SOQL injection attacks through malicious user input using type-casting methods.
Comparison: Secure vs Insecure SOQL
| Feature | Insecure Approach | Secure Approach |
|---|---|---|
| Query Type | Dynamic SOQL | Static SOQL |
| Input Handling | String Concatenation | Bind Variables |
| Security | High Risk | Safe |
| Maintainability | Difficult | Easy |
| Recommended | No | Yes |
Frequently Asked Questions
1. What is SOQL Injection?
SOQL Injection is a security vulnerability in which attackers manipulate SOQL queries with user input to access unauthorized data.
2. Is SOQL Injection dangerous?
Yes, it can expose sensitive data even though SOQL cannot delete or update records directly.
3. What is the best way to prevent SOQL Injection?
Using bind variables is the safest and most recommended method.
4. Can SOQL Injection delete data?
No, SOQL only supports SELECT queries, but it can expose confidential data.
Conclusion
SOQL Injection is a critical security issue in Salesforce, especially when working with dynamic queries. Even though SOQL is safer than SQL, improper coding practices can still expose your data.
To protect your application:
- Use bind variables
- Validate input
- Avoid dynamic queries
- Follow best practices
By implementing these techniques, you can build secure and scalable Salesforce applications.
You may also like to read:
- Difference between SOQL and SOSL in Salesforce
- Salesforce Relationship Queries in SOQL
- Query Salesforce Picklist Field values using SOQL
- Aggregate Query in Salesforce SOQL
- DATE Clause in SOQL
I am Bijay Kumar, the founder of SalesforceFAQs.com. Having over 10 years of experience working in salesforce technologies for clients across the world (Canada, Australia, United States, United Kingdom, New Zealand, etc.). I am a certified salesforce administrator and expert with experience in developing salesforce applications and projects. My goal is to make it easy for people to learn and use salesforce technologies by providing simple and easy-to-understand solutions. Check out the complete profile on About us.