Checkmarx for Salesforce means running Checkmarx SAST against your Apex and Visualforce code to catch SOQL injection, cross-site scripting, and CRUD/FLS enforcement gaps before they ship to your org. Salesforce is not just configuration; custom Apex classes, triggers, and Visualforce pages are real application code with real vulnerability classes, and a Salesforce Checkmarx scan applies static analysis to exactly that code.
This guide covers what the pairing detects, the Salesforce-specific issues that generic SAST advice misses, and how to work through the findings.
Why Salesforce needs SAST at all
There is a persistent assumption that because Salesforce is a managed platform, the security is handled for you. The platform hardens the infrastructure, but your custom code runs in that platform with your data, and it can be as insecure as any hand-written application. Apex has its own injection surface (SOQL and SOSL), Visualforce can render unescaped user input, and the platform's sharing and field-level security model is easy to bypass in code without realizing it.
Checkmarx supports Apex as a scanned language, so it can trace tainted data through Apex classes and Visualforce controllers the same way it does for Java or C#. That source-to-sink tracing is what surfaces the Salesforce-specific issues below.
SOQL injection
The Salesforce analog of SQL injection is SOQL injection, and it appears when user input is concatenated into a dynamic query. Checkmarx flags the path from the input source to the Database.query sink.
The illustrative anti-pattern:
// Flagged: user input concatenated into a dynamic SOQL query
String name = ApexPages.currentPage().getParameters().get('name');
String q = 'SELECT Id FROM Contact WHERE Name = \'' + name + '\'';
List<Contact> results = Database.query(q);
The remediation is variable binding, which keeps the input as data rather than query structure:
// Clean: bind variable
String name = ApexPages.currentPage().getParameters().get('name');
List<Contact> results =
[SELECT Id FROM Contact WHERE Name = :name];
Where dynamic SOQL is genuinely required, String.escapeSingleQuotes() on the untrusted fragment is the platform-provided sanitizer, and Checkmarx can be tuned to recognize it.
XSS in Visualforce and Lightning
Visualforce escapes expressions by default, but that protection is lost the moment a developer sets escape="false" on an <apex:outputText> or renders user input through unescaped mechanisms. Checkmarx flags input that reaches an output sink without encoding. The fix is to keep default escaping on and reserve escape="false" for content you have already sanitized. In Lightning Web Components the equivalent concern is unsafe DOM insertion, and the same source-to-sink logic applies.
CRUD and FLS enforcement
This is the Salesforce-specific class that generic SAST guidance tends to skip. Apex runs in system context by default, which means a query can return or modify records the running user has no permission to see or edit, silently bypassing object permissions (CRUD) and field-level security (FLS). Checkmarx query packs for Apex include checks for missing CRUD/FLS enforcement.
The modern remediation is to use user-mode database operations, for example WITH USER_MODE on a query or the user-mode Database methods, and to prefer with sharing classes so record-level sharing rules apply. Stripping inaccessible fields with Security.stripInaccessible() is another platform-provided control Checkmarx recognizes.
Working through Salesforce findings
A few things make the Checkmarx Salesforce workflow smoother:
- Scan from source control, not the org. Keep your Apex and Visualforce in a repository and scan it in CI, so findings map to reviewable diffs rather than a live org state.
- Expect CRUD/FLS noise, and triage it deliberately. Many CRUD/FLS findings are real design gaps, but some are handled by a shared access layer the engine does not recognize. Register that layer as a custom sanitizer so it is not re-flagged every scan.
- Fix by pattern, not by line. SOQL injection and missing FLS usually recur across many classes with one root cause. Fixing the pattern clears findings in bulk.
SAST on Apex covers your first-party code. It does not cover the security of managed packages you install from the AppExchange, which are third-party dependencies with their own risk. Treat those with the same scrutiny you would give any open source component, and cover your broader stack with software composition analysis. The Safeguard academy has more on how SAST and dependency scanning divide responsibility.
FAQ
Can Checkmarx scan Salesforce Apex code?
Yes. Checkmarx SAST supports Apex as a scanned language and can trace tainted data through Apex classes, triggers, and Visualforce controllers. It detects SOQL injection, cross-site scripting in Visualforce, and missing CRUD/FLS enforcement, among other query patterns.
What is SOQL injection and how does Checkmarx find it?
SOQL injection is the Salesforce equivalent of SQL injection, where user input concatenated into a dynamic query can alter its structure. Checkmarx traces the path from the input source to a Database.query sink and flags it. Use bind variables, or String.escapeSingleQuotes() for unavoidable dynamic queries.
Does Checkmarx catch Salesforce CRUD and FLS issues?
Yes, its Apex query packs include checks for missing object-permission (CRUD) and field-level security (FLS) enforcement, since Apex runs in system context by default. Remediate with user-mode database operations, with sharing classes, and Security.stripInaccessible().
Does scanning cover AppExchange managed packages?
No. Checkmarx SAST scans your own Apex and Visualforce source. Installed managed packages are third-party code and fall under dependency and supply chain review, so evaluate them separately rather than assuming a Checkmarx Salesforce scan covers them.