Home / security / secure-coding-review-checklist
secure-coding-review-checklist
Use this skill to audit Apex, Visualforce, LWC, and Aura code for Salesforce security review readiness — covering CRUD/FLS enforcement, SOQL injection, XSS, CSRF, and open redirects. NOT for network-level penetration testing or Shield Platform Encryption key management — use security/platform-encryption. NOT for fixing a single query's injection or FLS gap — use apex/soql-security.
Open the skill folder on GitHub
Secure Coding Review Checklist
This skill activates when a practitioner needs to audit Salesforce custom code for security vulnerabilities before an AppExchange security review, internal security audit, or ISV partner submission. It produces a structured, prioritized set of findings covering the vulnerability categories that cause the most review failures: CRUD/FLS gaps, SOQL/SOSL injection, cross-site scripting (XSS), CSRF, and open redirects.
Before Starting
Gather this context before working on anything in this domain:
- Confirm whether the code runs in a managed package context (namespace prefix) or unmanaged, as this changes sharing and access enforcement defaults.
- Identify the Apex sharing model per class:
with sharing,without sharing,inherited sharing, or no keyword. With no keyword the default is version-gated — a class saved at API 67.0+ runswith sharing, and at 66.0 and below it runswithout sharing. The inheritance rule bites too: once any class in the call chain is saved at 67.0+, the chain from there runswith sharing— a bare 67.0+ callee is not pulled down towithout sharingby awithout sharingcaller. The gate is the<apiVersion>in each class's.cls-meta.xml, not the org's release, so collect that value alongside the keyword. Triggers are a special case, but not the one usually assumed: they cannot carry a sharing keyword at any version, yet their database operations still take an access mode per statement, and at 67.0+ a bare one runs in user mode — which overrides the implicitwithout sharingand enforces sharing, FLS and CRUD. Record the trigger's own.trigger-meta.xmlapiVersion and read each query's access mode; do not infer "unenforced" from the missing keyword (Gotcha 1 below). Full table: