CRUD and Field-Level Security Enforcement
CRUD (Create, Read, Update, Delete) and Field-Level Security (FLS) enforcement are critical security mechanisms in Salesforce that ensure users can only access and manipulate data they are authorized to handle. **CRUD Security** controls object-level permissions, determining whether a user can cre… CRUD (Create, Read, Update, Delete) and Field-Level Security (FLS) enforcement are critical security mechanisms in Salesforce that ensure users can only access and manipulate data they are authorized to handle. **CRUD Security** controls object-level permissions, determining whether a user can create, read, update, or delete records of a specific object. These permissions are defined through Profiles and Permission Sets. **Field-Level Security (FLS)** operates at a more granular level, controlling visibility and editability of individual fields on an object. Even if a user has read access to an object, FLS can restrict access to specific sensitive fields. **Why Enforcement Matters:** Salesforce does NOT automatically enforce CRUD and FLS in Apex code. While standard UI components like Lightning pages respect these settings, custom Apex code runs in system context, bypassing these security checks. Developers must explicitly enforce them. **Enforcement Methods:** 1. **WITH SECURITY_ENFORCED** - Added to SOQL queries to enforce both CRUD and FLS. If the user lacks access, it throws an insufficient access exception. Example: `SELECT Name FROM Account WITH SECURITY_ENFORCED` 2. **Schema.DescribeSObjectResult & Schema.DescribeFieldResult** - Programmatic checking using methods like `isAccessible()`, `isCreateable()`, `isUpdateable()`, and `isDeletable()`. 3. **Security.stripInaccessible()** - Introduced in API v45.0, this method strips fields the user cannot access from query results or DML operations. It accepts an AccessType parameter (READABLE, CREATABLE, UPDATABLE, UPSERTABLE) and returns sanitized records. 4. **Lightning Data Service (LDS)** - In Lightning components, LDS automatically respects CRUD and FLS, making it the recommended approach for data operations in the UI layer. **Best Practices:** - Always enforce CRUD/FLS in custom Apex controllers - Use `Security.stripInaccessible()` for cleaner handling - Leverage LDS in Lightning components whenever possible - Test with non-admin users to validate enforcement Failure to enforce CRUD and FLS can lead to security vulnerabilities and is a common reason for AppExchange security review failures.
CRUD and Field-Level Security (FLS) Enforcement – Salesforce Platform Developer 1 Guide
Introduction
One of the most critical topics on the Salesforce Platform Developer 1 exam is understanding how to properly enforce CRUD (Create, Read, Update, Delete) permissions and Field-Level Security (FLS) in your Apex code and Lightning components. Salesforce is a multi-tenant platform, and respecting the security model is essential to building secure, compliant applications. This guide covers why CRUD/FLS enforcement matters, what it is, how it works, and how to confidently answer exam questions on this topic.
Why Is CRUD/FLS Enforcement Important?
Salesforce administrators spend significant time configuring object-level and field-level permissions through profiles, permission sets, and permission set groups. These configurations control which users can create, read, update, or delete specific objects and which fields they can see or edit. If a developer writes Apex code that bypasses these settings, the entire security model breaks down.
Key reasons CRUD/FLS enforcement matters:
• Security Compliance: Applications that ignore CRUD/FLS can expose sensitive data (e.g., salary, SSN, health records) to unauthorized users.
• AppExchange Security Review: Salesforce requires that all managed packages pass a security review. Apps that do not enforce CRUD/FLS will fail this review.
• Trust: Salesforce's platform is built on trust. Respecting the sharing and security model is a foundational principle.
• Best Practice: Enforcing CRUD/FLS is a Salesforce-recommended best practice for all custom development.
What Is CRUD?
CRUD stands for Create, Read, Update, Delete. These are object-level permissions that determine whether a user can perform these four operations on a given sObject (e.g., Account, Contact, or a custom object).
• Create: Can the user insert new records of this object type?
• Read: Can the user query or view records of this object type?
• Update: Can the user modify existing records of this object type?
• Delete: Can the user remove records of this object type?
These permissions are configured on Profiles and Permission Sets by administrators.
What Is Field-Level Security (FLS)?
Field-Level Security controls access at the field level within an object. Even if a user has Read access to an object, FLS can restrict them from seeing or editing specific fields on that object.
FLS has two settings per field per profile:
• Visible: Can the user see this field?
• Read-Only: Can the user only read (but not edit) this field?
For example, a user might have Read access to the Contact object but might not have visibility into the Social_Security_Number__c field due to FLS restrictions.
The Core Problem: Apex Runs in System Context
By default, Apex code runs in system context, meaning it does not automatically respect the running user's CRUD or FLS permissions. This is different from standard Salesforce UI operations (like editing a record through the browser), which always enforce these permissions.
This means that if you write a SOQL query in Apex, it will return all fields and all records regardless of whether the running user has permission to see them—unless you explicitly enforce CRUD/FLS in your code.
How to Enforce CRUD in Apex
There are several approaches to enforcing CRUD permissions:
1. Schema Describe Methods (Legacy Approach)
You can use the Schema.DescribeSObjectResult class to manually check permissions before performing DML:
• Schema.sObjectType.Account.isCreateable() – checks Create permission
• Schema.sObjectType.Account.isAccessible() – checks Read permission
• Schema.sObjectType.Account.isUpdateable() – checks Update permission
• Schema.sObjectType.Account.isDeletable() – checks Delete permission
Example pattern:
if (Schema.sObjectType.Account.isUpdateable()) {
update accountRecord;
} else {
throw new SecurityException('Insufficient permissions to update Account.');
}
2. WITH SECURITY_ENFORCED (SOQL Keyword)
Added in later releases, the WITH SECURITY_ENFORCED clause can be appended to SOQL queries to enforce both object-level and field-level read access. If the running user does not have access to any object or field referenced in the query, a System.QueryException is thrown at runtime.
Example:
List<Account> accounts = [SELECT Id, Name, AnnualRevenue FROM Account WITH SECURITY_ENFORCED];
Key points about WITH SECURITY_ENFORCED:
• It checks FLS on all fields in the SELECT clause and the object in the FROM clause.
• It also checks fields used in WHERE, ORDER BY, and relationship fields.
• If any field or object fails the check, it throws an exception—it does not silently strip inaccessible fields.
• It enforces read access only (not create, update, or delete).
3. Security.stripInaccessible() Method (Preferred Modern Approach)
The Security.stripInaccessible() method was introduced to provide a more flexible way to enforce FLS. Instead of throwing an exception, it removes inaccessible fields from the records and returns a cleaned SObjectAccessDecision.
This method accepts an AccessType parameter:
• AccessType.CREATABLE – enforces create FLS
• AccessType.READABLE – enforces read FLS
• AccessType.UPDATABLE – enforces update FLS
• AccessType.UPSERTABLE – enforces upsert FLS
Example for reading:
List<Account> accounts = [SELECT Id, Name, AnnualRevenue FROM Account];
SObjectAccessDecision decision = Security.stripInaccessible(AccessType.READABLE, accounts);
List<Account> sanitizedAccounts = decision.getRecords();
Example for creating:
SObjectAccessDecision decision = Security.stripInaccessible(AccessType.CREATABLE, newAccounts);
insert decision.getRecords();
Key points about stripInaccessible():
• It does not throw an exception; instead, it silently strips fields the user cannot access.
• You can use decision.getRemovedFields() to see which fields were removed.
• It works for read, create, update, and upsert operations.
• This is the recommended approach for most scenarios.
• Accessing a stripped field on the returned records will throw a SObjectException.
4. WITH USER_MODE and SYSTEM_MODE (Newest Approach)
Salesforce introduced USER_MODE and SYSTEM_MODE keywords for SOQL and DML operations. When you use USER_MODE, the operation respects the running user's CRUD, FLS, and sharing rules.
SOQL example:
List<Account> accounts = [SELECT Id, Name FROM Account WITH USER_MODE];
DML example:
Database.insert(accountList, AccessLevel.USER_MODE);
Key points about USER_MODE:
• It enforces CRUD + FLS + Sharing all at once.
• For SOQL, inaccessible fields are silently removed from results (unlike WITH SECURITY_ENFORCED, which throws an exception).
• For DML, if the user lacks CRUD or FLS, a runtime exception is thrown.
• This is the most comprehensive and modern approach.
How to Enforce FLS in Apex
FLS enforcement overlaps with the methods described above, but here are field-specific checks using the legacy Schema describe approach:
• Schema.sObjectType.Account.fields.AnnualRevenue.getDescribe().isAccessible() – can the user read this field?
• Schema.sObjectType.Account.fields.AnnualRevenue.getDescribe().isCreateable() – can the user set this field on insert?
• Schema.sObjectType.Account.fields.AnnualRevenue.getDescribe().isUpdateable() – can the user edit this field on update?
While these manual checks work, they are verbose and error-prone. The Security.stripInaccessible() method and WITH USER_MODE are preferred because they handle all fields automatically.
CRUD/FLS in Lightning Web Components (LWC)
When building Lightning Web Components:
• Lightning Data Service (LDS): Automatically enforces CRUD and FLS. If you use lightning-record-form, lightning-record-view-form, lightning-record-edit-form, or the getRecord wire adapter, CRUD and FLS are automatically respected. This is the preferred approach.
• Apex Controllers: If your LWC calls an Apex method via @AuraEnabled, you must manually enforce CRUD/FLS in the Apex method because Apex runs in system context.
CRUD/FLS in Visualforce
Visualforce pages using standard controllers automatically enforce CRUD and FLS. However, Visualforce pages using custom controllers or controller extensions with custom queries do not automatically enforce CRUD/FLS—you must do so manually in your Apex code.
Summary Comparison Table
Method → Behavior
• Schema Describe checks → Manual, verbose; checks one field/object at a time. Developer must handle the logic.
• WITH SECURITY_ENFORCED → Enforces read FLS/CRUD on SOQL. Throws QueryException if access denied. Does not strip fields.
• Security.stripInaccessible() → Strips inaccessible fields silently. Works for CRUD and FLS. Supports read, create, update, upsert.
• WITH USER_MODE → Enforces CRUD + FLS + Sharing. Silently strips inaccessible fields for SOQL. Throws exception for DML violations. Most comprehensive.
Common Exam Scenarios
Scenario 1: A developer writes a SOQL query in an Apex class and wants to ensure FLS is respected. The query should not fail but should simply omit fields the user cannot see.
→ Answer: Use Security.stripInaccessible(AccessType.READABLE, records) or WITH USER_MODE.
Scenario 2: A developer wants to ensure that if the user does not have read access to any field in the query, the entire query fails.
→ Answer: Use WITH SECURITY_ENFORCED.
Scenario 3: A developer needs to insert records and ensure only fields the user can create are included.
→ Answer: Use Security.stripInaccessible(AccessType.CREATABLE, records) before the insert, or use Database.insert(records, AccessLevel.USER_MODE).
Scenario 4: A Lightning Web Component uses a standard lightning-record-form.
→ Answer: CRUD and FLS are automatically enforced by Lightning Data Service. No additional code is needed.
Scenario 5: A developer uses a Visualforce page with a custom controller.
→ Answer: CRUD and FLS are NOT automatically enforced. The developer must enforce them in the Apex controller.
Exam Tips: Answering Questions on CRUD and Field-Level Security Enforcement
1. Remember that Apex runs in system context by default. This is the fundamental reason CRUD/FLS enforcement is needed. Any question that mentions Apex accessing data without explicitly mentioning enforcement is likely testing whether you know this.
2. Know the difference between WITH SECURITY_ENFORCED and Security.stripInaccessible(). The former throws an exception; the latter silently strips fields. Exam questions often present scenarios where one approach is more appropriate than the other.
3. WITH USER_MODE is the most comprehensive option. If a question asks for the approach that enforces CRUD, FLS, and sharing rules together, WITH USER_MODE (or AccessLevel.USER_MODE for DML) is the answer.
4. Lightning Data Service always enforces CRUD/FLS. If a question involves standard LWC components like lightning-record-form or wire adapters like getRecord, the answer about security enforcement is that it is handled automatically.
5. Standard controllers in Visualforce enforce CRUD/FLS; custom controllers do not. This is a frequently tested distinction.
6. Look for the AccessType parameter. When a question mentions Security.stripInaccessible(), pay attention to whether the operation is a read, insert, update, or upsert—the correct AccessType must match the DML operation.
7. Schema.sObjectType checks are for CRUD; Schema.fields checks are for FLS. If a question asks about checking whether a user can delete a record, the answer involves isDeletable() at the object level. If it asks about field visibility, it involves isAccessible() at the field level.
8. Understand that WITH SECURITY_ENFORCED only works for SOQL read operations. It does not apply to DML. If a question asks about enforcing security on an insert or update, WITH SECURITY_ENFORCED is not the correct answer.
9. Be cautious of trick answers. Options like "running a query as a guest user" or "using without sharing" are not valid ways to enforce CRUD/FLS. Without sharing only affects record-level sharing, not CRUD or FLS.
10. Know that sharing rules and CRUD/FLS are different layers. Sharing rules (controlled by with sharing / without sharing keywords) determine which records a user can access. CRUD/FLS determines which objects and fields a user can access. The exam may test whether you can distinguish between these two concepts.
11. When in doubt, choose the declarative or built-in approach. Salesforce exam questions favor built-in platform features over manual code. If one answer involves manual Schema describe checks and another uses Security.stripInaccessible() or WITH USER_MODE, the latter is typically the preferred answer.
12. Remember the exception behavior. WITH SECURITY_ENFORCED throws a System.QueryException. Accessing a stripped field after stripInaccessible() throws a SObjectException. DML in USER_MODE throws a DmlException or SecurityException. Knowing which exception type corresponds to which method can help you eliminate incorrect answers.
By mastering these concepts and understanding when to apply each enforcement mechanism, you will be well-prepared to handle CRUD and FLS questions on the Salesforce Platform Developer 1 exam.
🎓 Unlock Premium Access
Salesforce Certified Platform Developer I + ALL Certifications
- 🎓 Access to ALL Certifications: Study for any certification on our platform with one subscription
- 2750 Superior-grade Salesforce Certified Platform Developer I practice questions
- Unlimited practice tests across all certifications
- Detailed explanations for every question
- PD1: 5 full exams plus all other certification exams
- 100% Satisfaction Guaranteed: Full refund if unsatisfied
- Risk-Free: 7-day free trial with all premium features!