Data security is the most important and most difficult aspect when it comes to Healthcare organizations, especially when ensuring the systems remain HIPAA complaint and maintain PHI/PII information safe. This effort is no less easy when you throw SaaS application in to mix. We will try here to address some common pitfalls and easy solutions to ensure that the clients do not falter on these compliance matters when it comes to Salesforce.

Let’s get some terms cleared out before we proceed with our approach:

Salesforce’s default HIPAA compliance features

  • Salesforce is a Business Associate under HIPAA, which requires them to apply safeguards and requirements that are outlined by HIPAA security Rule. This means that the underlying mechanism applied by Salesforce in their offering is HIPAA compliant.
  • Salesforce has defined TLS 1.1 as the minimum standard security protocol and by default requires HTTPS to access standard orgs.

Salesforce’s Customizable Features

Apart from these default features, Salesforce also provides various customizable features to allow customers to apply tighter security controls:

  • Customize user session security: Logout idle users
  • Disable caching usernames: Enforce users to enter username every time they login
  • Prevent PHI/PII information in sandboxes through refresh and cloning: We will touch this topic in detail below.

Salesforce Shield Platform Encryption

Salesforce provides add-on security features like Shield Platform Encryption:

CloudFountain’s custom approach to security. When we work with Healthcare clients, apart from applying the above practices and features, we apply additional solutions to ensure that there is no leakage when it comes to full sandbox refresh or cloning sandboxes.

Introducing SandboxPostCopy Interface

With Spring ’16 release, Salesforce introduced SandboxPostCopy interface. We have tried to leverage this interface to provide additional security when it comes to sandbox refresh and cloning.

In the below snippet, we have defined class CreateDummyEmails which implements the SandboxPostCopy interface:

global class CreateDummyEmails implements SandboxPostCopy {

view rawCreateDummyEmails.cls hosted with ❤ by GitHub

The init function calls two functions:

  • findEmailFields: Finds all the email fields in all the SObjects
  • cleanEmailFields: replaces the emails fields with PHI compliant email addresses
global static void init() {
// Map of sObject and list of email fields
Map < String, List < String >> soEmailFieldMap = findAllEmailFields();
// create dummy emails on Email fields found in the sObjects

view rawinit.CreateDummyEmails.cls hosted with ❤ by GitHub


public static Map < String, List < String >> findAllEmaiLFields() {
Map < String, List < String >> mSObjEmailFields = new Map < String, List < String >> ();
// Iterate through all SObjects
for (SObjectType sObjType: Schema.getGlobalDescribe().values()) {
DescribeSObjectResult sObjDescribe = sObjType.getDescribe();
// Avoid objects that cannot be queried or updated.
if (!sObjDescribe.isQueryable() || !sObjDescribe.isUpdateable()) continue;
String sObjName = sObjDescribe.getName();
// Iterate through all fields
for (SObjectField sObjField: sObjDescribe.fields.getMap().values()) {
DescribeFieldResult sObjFld = sObjField.getDescribe();
// Consider only Email fields
if (sObjFld.getType() != Schema.DisplayType.EMAIL) continue;
if (!sObjFld.isFilterable()) continue;
// Add all Email fields in the map.
if (mSObjEmailFields.containsKey(sObjName)) {
} else {
mSObjEmailFields.put(sObjName, new List < String > {
return mSObjEmailFields;

view rawfindAllEmaiLFields.CreateDummyEmails.cls hosted with ❤ by GitHub


public static void cleanEmailFields(Map < String, List < String >> mSobjField) {
// Iterate through SObject->Email Fields
for (String sObjName: mSobjField.keySet()) {
// Build a list of all fields that need to be queried
List < String > lstEmailFields = mSobjField.get(sObjName);
// Generate a SOQL query to get records with non null emails
String soql = createSOQL(sObjName, lstEmailFields);
List < SObject > sObjRecords = new List < SObject > ();
// Iterate through SObject records
for (SObject sObjRecord: Database.query(soql)) {
// Iterate through email fields found on SObject and replace with dummy values
for (String strField: lstEmailFields) {
String strEmail = (String) sObjRecord.get(strField);
if (String.isEmpty(strEmail)) continue;
sObjRecord.put(strField, strEmail.replaceAll(‘\W’, ‘_’) + ‘’);
update sObjRecords;

view rawcleanEmailFields.CreateDummyEmails.cls hosted with ❤ by GitHub

This is just a glimpse into a more sophisticated solution. Using custom metadata, you can use the same function to create dummy values on other fields e.g. patient name, address, phone numbers etc.

We would love to hear your feedback.

Author: CloudFountain

We started as a side business in 1999 and have since grown to become a leading provider of IT solutions for businesses. With around 30 employees across several countries, we offer a wide range of services, including IT support, hosting, and custom software development.Over the years, we have served approximately 1000 customers, ranging from small startups to large enterprises. Our mission is to provide cutting-edge technology solutions that help our clients achieve their business goals. We pride ourselves on our exceptional customer service and attention to detail, and we work closely with each client to understand their unique needs and provide tailored solutions that meet their specific requirements.At CloudFountain, we believe that technology can be a powerful tool for growth and success. That’s why we stay on top of the latest trends and advancements in the industry, so we can provide our clients with the best possible solutions. Whether you need IT support, hosting services, or custom software development, our team of experts is here to help. Contact us today to learn more about how we can help your business succeed.