Skip to main content

Salesforce standard SObject PII map

Salesforce ships dozens of standard SObjects (Account, Contact, Lead, Opportunity, Case, User, ...) with a known field shape. An Apex controller that SELECTs Email, Phone, Birthdate from one of these objects is processing PII whether or not the developer ever spells out "PII" in the code.

Vulkro carries an authoritative SF-only PII map keyed on (sobject, field) and consults it on every Apex SOQL or DML statement that references a standard SObject. The output is an informational finding per (sobject, field) pair that downstream compliance reports (GDPR RoPA, HIPAA, SOC2 CC6.8, NIST 800-53 SC-13) can ingest as evidence that the codebase IS touching regulated data.

Covered SObjects

Six standard SObjects are mapped:

  • Account (billing / shipping address fields, phone, fax, website, and the Person Account variant with Person* fields)
  • Contact (email, phone, mobile, mailing address, birthdate, name)
  • Lead (mirrors Contact for the prospect-facing field shape)
  • Opportunity (commercial-sensitive fields: amount, close date, forecast category)
  • Case (supplied email / phone, contact channels, description, subject)
  • User (email, username, federation identifier, phone, address, workforce information)

Tier scheme

Each field is tagged at one of three tiers:

  • Tier 1 (regulated PII): direct identifier, government ID, payment data, or login credentials. Reportable under GDPR Art 9, HIPAA, PCI-DSS. Emitted at Medium severity, High confidence.
  • Tier 2 (personal information): personal detail or contact channel. Reportable under GDPR Art 6, CCPA personal information. Emitted at Low severity, High confidence.
  • Tier 3 (commercial-sensitive): not regulated PII but worth surfacing for SOC2 CC6.8 (confidentiality) purposes. Emitted at Low severity, Medium confidence.

Custom objects are not covered

Fields on MyObj__c (custom object) or MyField__c (custom field) are not in the map: their semantics are project-specific. The generic naming catalog in vulkro (the same one that powers the language- agnostic PII detector) handles those via field-name matching.

List<Contact> cons = [SELECT Id, Email, Phone FROM Contact];
// Vulkro emits Contact.Email (Medium) and Contact.Phone (Medium).

List<MyObj__c> cs = [SELECT Id, Email__c FROM MyObj__c];
// No SF-PII-map finding (custom object); the generic naming catalog
// applies based on the field name.

Example output

$ vulkro scan force-app
...
[MEDIUM] Apex SOQL accesses `Contact.Email` (tier-1 (regulated PII)
per Salesforce field-level reference). Any code path that reads this
field is processing regulated personal data; ensure access is gated
by an FLS / `WITH SECURITY_ENFORCED` check and that downstream
serialisation (Apex REST, Visualforce, LWC `@wire` returns) does not
expose the value to users who would not be entitled to see it on the
record page.

[LOW] Apex DML `update` writes a `Contact` record. This standard
SObject carries regulated personal data (per Salesforce field-level
reference); the operation should run under user mode (`as user` /
`WITH SECURITY_ENFORCED` on the prior SELECT) and the source fields
should be allow-listed against attacker-controlled input to defend
against mass-assignment.

What is not covered yet

  • Cross-namespace references (acme__Account) resolve to the bare object name after the namespace prefix; if a managed package redefines the field shape Vulkro will mis-tag.
  • The Health Cloud / Industries / Education Cloud standard SObjects are not yet in the map; they ship with their own field-level reference docs that we plan to fold in.
  • The PII map is informational: by design it does not change scan exit codes (so a clean codebase that legitimately processes PII still passes the gate). The findings DO contribute to the compliance evaluation when you run vulkro compliance . --profile gdpr or --profile nist-800-53.