Skip to main content

Encrypted fields show unencrypted value when accessing via apex

When querying records in Apex,  the result includes raw values instead of a mask for encrypted fields even though the user does not have access to view the encrypted data. This results in a UI displaying actual data because the UI is using Apex. 

Steps to reproduce :

  • Create a new custom object named Sample
  • Create a custom field on object Sample named Sensitive__c and set the type to Text (Encrypted)
  • Create a new record in the custom object Sample and set the Encrypted__c field to the value TEST
  • Save the record.
  • Observe that if your profile don't have  View Encrypted Data permission, you see a field mask on the field Sensitive__c on the detail page 
  • If you see the value TEST and you do not see the mask, Then your profile has View Encrypted Data permission.
  • Remove View Encrypted Data permission from your profile so that field mask on the field Sensitive__c appear.
  • Create a new Apex class named Sample with the below code 

@RestResource(urlMapping='/Sample/*')

global class Sample {

public static List<SObject> getSObjects() {

return Database.query('SELECT Sensitive__c FROM Sample__c where Sensitive__c!= null Limit 10 ');

}

@HttpGet

global static String getSerializedRecords() {

return JSON.serialize(Sample.getSObjects());

}

}

  • Invoke the get endpoint /services/apexrest/Sample/?getSerializedRecords

Expected: The response displays the **** mask for the Sensitive__c field

Actual: The response displays the unencrypted value TEST for the Sensitive__c field


Masking is not supported for Apex Serialisation. It is only supported for simple Classic View. We will have to use Field Level security to restrict the encrypted field access to the user. In case, FLS is already granted, We will have to implement our own field masking.

Sample Code to implement field masking

@RestResource(urlMapping='/Sample/*')

global class Sample {

    public static List<SObject> getSObjects() {

  List<SObject> results = new  List<SObject>();

    String mask ='*';

  // To check whether he user has view Encrypted data permissions

    List<PermissionSetAssignment> psaEncrypt = [SELECT Id FROM PermissionSetAssignment

    WHERE PermissionSet.PermissionsViewEncryptedData = true AND AssigneeId = :userInfo.getUserId()];

  if(psaEncrypt.isEmpty()) //No permission 'view encrypted data' to the user

        {

        for(Account s : [SELECT Sensitive__c FROM Sample__c order by CreatedDate desc limit 100])

         {

        if (!String.isEmpty(s.Sensitive__c))

          s.Sensitive__c = mask.repeat( s.Sensitive__c.length());

         results.add(s);

         }

         return results;

      }

      else

      return Database.query('SELECT Sensitive__c FROM Sample__c order by CreatedDate desc limit 100');

    }

    @HttpGet

    global static String getSerializedRecords() {

        return JSON.serialize(Sample.getSObjects());

    }

}

i hope this helps. Thank you for reading this article. Cheers:)

Comments