Enforce Field-Level Security in Apex (Beta)

The stripInaccessible() security feature for field-level data protection has moved from pilot to beta and is available in production orgs. In Winter ’20, we extended the feature for subqueries and added the enum value UPSERTABLE to System.AccessType. Use this new enum with the stripInaccessible method to enforce field- and object-level checks for both insert and update.

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



As a beta feature, stripInaccessible method is a preview and isn’t part of the “Services” under your master subscription agreement with Salesforce. Use this feature at your sole discretion, and make your purchase decisions only on the basis of generally available products and features. Salesforce doesn’t guarantee general availability of this feature within any particular time frame or at all, and we can discontinue it at any time. This feature is for evaluation purposes only, not for production use. It’s offered as is and isn’t supported, and Salesforce has no liability for any harm or damage arising out of or in connection with it. All restrictions, Salesforce reservation of rights, obligations concerning the Services, and terms for related Non-Salesforce Applications and Content apply equally to your use of this feature. You can provide feedback and suggestions for this feature in the Security.stripInaccessible group in the IdeaExchange.

Why: You can use the stripInaccessible method to strip the fields that the current user can’t access from query and subquery results. You can use it to remove inaccessible fields from sObjects before a DML operation to avoid exceptions. You can also use the method to sanitize sObjects that have been deserialized from an untrusted source.

How: The stripInaccesible method checks the source records for subquery fields that don’t meet the field-level security check for the current user. The method returns a list of sObjects that contain only the fields that are accessible to the current user. If the user doesn’t have access to the relationship field from child to parent, the return list of sObjects doesn’t include the child relationship.

If the user doesn’t have permission to read the Phone field of a Contacts object, this example code removes the subquery field before reading the records. The DML operation completes without throwing an exception.
List<Account> accountsWithContacts =
	[SELECT Id, Name, Phone,
	    (SELECT Id, LastName, Phone FROM Account.Contacts)
	FROM Account];
// Strip fields that are not readable
   SObjectAccessDecision decision = Security.stripInaccessible(
// Print stripped records
   for (Integer i = 0; i < accountsWithContacts.size(); i++) 
      System.debug('Insecure record access: '+accountsWithContacts[i]);
      System.debug('Secure record access: '+decision.getRecords()[i]);
// Print modified indexes
   System.debug('Records modified by stripInaccessible: '+decision.getModifiedIndexes());
// Print removed fields
   System.debug('Fields removed by stripInaccessible: '+decision.getRemovedFields());