Enforce Field-Level Security in Apex (Pilot)

Apex has a new security feature for field-level data protection, which is accessed through the Security and SObjectAccessDecision classes. To ensure secure processing in Apex in the context of the current user’s read, create, or update operation, use the stripInaccessible method. Based on the field-level security of the current user, this method can be used to strip the fields from query results that the user can’t access. The method can also be used to remove inaccessible fields from sObjects before a DML operation to avoid exceptions and to sanitize sObjects that have been deserialized from an untrusted source.

Where: This change applies to Lightning Experience and Salesforce Classic in Enterprise, Performance, Unlimited, and Developer editions.

Note

Note

This pilot feature is available automatically in sandbox, developer, and scratch organizations as a pilot program. The functionality of this feature is subject to change, and is not available for production organizations while in pilot. Pilot programs are subject to change, and we can’t guarantee acceptance. This feature isn’t generally available unless or until Salesforce announces its general availability in documentation or in press releases or public statements. We can’t guarantee general availability within any particular time frame or at all. Make your purchase decisions only on the basis of generally available products and features. You can provide feedback and suggestions for this feature in the Security.stripInaccessible group in the IdeaExchange.

How: The stripInaccesible method checks the source records for fields that don’t meet the field-level security check for the current user and creates a return list of sObjects. The return list is identical to the source records, except that the fields that are inaccessible to the current user are removed.

Example

If the user doesn’t have the permission to create the Probability field of an Opportunity object, this example removes the Probability field before creating the records. The DML operation is completed without throwing an exception.
List<Opportunity> opportunities = new List<Opportunity>{
    new Opportunity(Name='Opportunity1'),
    new Opportunity(Name='Opportunity2', Probability=95)
};

// Strip fields that are not creatable
SObjectAccessDecision decision = Security.stripInaccessible(
    AccessType.CREATABLE,
    opportunities);

// Print stripped records
for (SObject strippedOpportunity : decision.getRecords()) {
    System.debug(strippedOpportunity);
}

// print modified indexes
System.debug(decision.getModifiedIndexes());

// Print removed fields
System.debug(decision.getRemovedFields());

//System.debug Output
// DEBUG|Opportunity:{Name=Opportunity1}
// DEBUG|Opportunity:{Name=Opportunity2}
// DEBUG|{1}
// DEBUG|{Opportunity={Probability}}