Skip to main content

Code reviews rule: Insecure storage of sensitive information

Written by David Martin

Insecure storage of sensitive information

Why is this an issue?

Storing sensitive information (passwords, tokens, secrets) in standard Salesforce fields creates security risks:

  • Data is visible to users with field access

  • Data may appear in reports and exports

  • Data is included in backups without encryption

  • Audit and compliance requirements may be violated

This rule applies to both Apex classes and triggers. It uses taint analysis to detect sensitive data flowing into database write operations (DML statements and Database class methods). It identifies sensitive data through:

  • Sensitive keywords: string literals or identifiers containing words like secret, password, token, encryption, certificate, crypto, secure, passphrase, private, or ssn

  • Field metadata: field access on custom fields whose securityClassification is set to Internal, Confidential, Restricted, or MissionCritical

  • System methods: calls to UserInfo.getSessionId()

In addition, this rule scans custom object and custom field metadata for field definitions whose names contain sensitive keywords. Fields on protected custom metadata types are excluded from this check.

Examples

Sensitive data written via DML

Example of incorrect code:

public class CredentialManager {
public void saveApiKey(String token) {
Integration_Settings__c setting = new Integration_Settings__c();
setting.API_Token__c = token;
// Violation: sensitive data is persisted in the database
insert setting;
}
}

Example of correct code:

public class CredentialManager {
public void callApi() {
// Authentication is handled by Named Credentials β€” no secrets in the database
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:MyNamedCredential/api/data');
new Http().send(req);
}
}

Session ID written via Database class

Example of incorrect code:

public class AuditService {
public void logActivity() {
Audit_Log__c log = new Audit_Log__c();
log.Session__c = UserInfo.getSessionId();
// Violation: session ID is persisted in the database
Database.insert(log, false);
}
}

Example of correct code:

public class AuditService {
public void logActivity() {
// Log the activity without persisting the raw session ID
Audit_Log__c log = new Audit_Log__c();
log.Action__c = 'User performed action';
log.Timestamp__c = Datetime.now();
Database.insert(log, false);
}
}

Sensitive field based on security classification

Custom fields whose metadata sets securityClassification to Confidential, Restricted, Internal, or MissionCritical are treated as sensitive sources regardless of their name.

Example of incorrect code:

public class DataService {
public void copyData() {
Case_Log_Review__c source = getCaseLog();
Account target = new Account();
// SSN_Number__c has securityClassification set to Confidential
target.Name = source.SSN_Number__c;
Database.insert(target, false); // Violation: sensitive field data persisted
}
}

Example of correct code:

public class DataService {
public void copyData() {
Case_Log_Review__c source = getCaseLog();
Account target = new Account();
// Only copy non-sensitive fields
target.Name = source.Description__c;
Database.insert(target, false);
}
}

How can I fix violations?

  1. Use Named Credentials: Store API credentials in Named Credentials.

  2. Use Protected Custom Settings: For sensitive configuration that should be hidden from most users.

  3. Use Platform Encryption: Enable Shield Platform Encryption for sensitive fields.

  4. Use External Services: Store secrets in secure external vaults (e.g., AWS Secrets Manager).

  5. Remove sensitive data: If sensitive data was stored in fields, migrate it and delete the old data.

When should I disable this rule?

You may need to dismiss specific violations if the sensitive data is already protected through Shield Platform Encryption or if the field is stored in a Protected Custom Setting that is not accessible to end users. You may also disable this rule if your application intentionally persists sensitive data with compensating controls (e.g., encryption at the application layer) that static analysis cannot detect.

Resources

Did this answer your question?