Skip to main content

Code reviews rule: Apex CRUD/FLS

Written by David Martin
Updated this week

Apex CRUD/FLS

Why is this an issue?

CRUD (Create, Read, Update, Delete) and FLS (Field-Level Security) enforcement ensures that your Apex code respects the object and field permissions configured for users. When code runs in system context (such as from @AuraEnabled methods, triggers, or Visualforce controllers), it bypasses the user's permissions by default.

This rule detects database operations (insert, update, delete) that:

  1. Run in a system context (reachable from triggers, LWC, Visualforce, or auto-launched flows)

  2. Do not verify object-level permissions before executing

  3. Process data from potentially unsafe sources without sanitization

Examples

Example of incorrect code:

public class AccountController {
@AuraEnabled
public static void createAccount(String name) {
Account acc = new Account(Name = name);
insert acc; // No CRUD check before insert
}
}

Example of correct code:

public class AccountController {
@AuraEnabled
public static void createAccount(String name) {
// Check if user can create Accounts
if (!Schema.sObjectType.Account.isCreateable()) {
throw new AuraHandledException('Insufficient permissions');
}

Account acc = new Account(Name = name);
insert acc;
}
}

Or use Security.stripInaccessible():

public class AccountController {
@AuraEnabled
public static void createAccount(String name) {
Account acc = new Account(Name = name);
SObjectAccessDecision decision = Security.stripInaccessible(
AccessType.CREATABLE,
new List<Account>{ acc }
);
insert decision.getRecords();
}
}

Or use AS USER for DML operations:

public class AccountController {
@AuraEnabled
public static void createAccount(String name) {
Account acc = new Account(Name = name);
insert as user acc;
}
}

Example of incorrect code with a SOQL query:

public class ContactController {
@AuraEnabled
public static List<Contact> getContacts() {
// No FLS enforcement on query
return [SELECT Name, Phone FROM Contact LIMIT 100];
}
}

Example of correct code with a SOQL query:

public class ContactController {
@AuraEnabled
public static List<Contact> getContacts() {
return [SELECT Name, Phone FROM Contact WITH USER_MODE LIMIT 100];
}
}

How can I fix violations?

  1. Check object permissions: Use Schema.sObjectType.ObjectName.isCreateable(), isDeletable(), etc.

  2. Use Security.stripInaccessible(): Automatically removes inaccessible fields

  3. Use USER_MODE: Add AS USER to DML or WITH USER_MODE to SOQL queries

When should I disable this rule?

You may want to dismiss this issue if:

  • The code intentionally bypasses security for legitimate system operations

  • The object being modified is a system object that all users should access

  • You have implemented permission checks in a way the rule cannot detect

Resources

Did this answer your question?