This page organizes security best practices and common anti-patterns by category. For CTA scenarios, demonstrating awareness of anti-patterns is just as important as knowing best practices — the board often presents scenarios with built-in anti-patterns to see if you identify and correct them.
Sharing Model Best Practices
Best Practices
| Practice | Why It Matters |
|---|
| Start with Private OWD for all objects, then open up | You can add access but never remove it below OWD. Starting open is irreversible without changing OWD |
| Design role hierarchy for data access, not HR org chart | The hierarchy controls record visibility, not reporting. An org chart hierarchy creates unnecessary sharing |
| Prefer criteria-based sharing rules over ownership-based when possible | Criteria rules are based on field values (stable), not record ownership (changes frequently) |
| Limit sharing rules to 50 per object as a practical maximum | More than 50 indicates the OWD or hierarchy design is wrong. Sharing recalculation time increases linearly |
| Use public groups to abstract sharing targets | Groups can be managed without modifying sharing rules. Share with “West Region Team” not individual roles |
| Document every sharing mechanism and its justification | The CTA board will ask why you chose each mechanism. Future admins need to understand the design |
| Test sharing with different user profiles before go-live | Create test users at each hierarchy level and verify record visibility matches requirements |
Anti-Patterns
| Anti-Pattern | Risk | Correct Approach |
|---|
| Setting OWD to Public Read/Write “because it’s simpler” | Cannot restrict access for any user; no audit trail of access decisions | Start Private; open up with sharing rules |
| Mirroring the HR org chart in role hierarchy | Creates deep hierarchies (10+ levels); performance degradation; unnecessary visibility | Design for data access patterns; keep 5-7 levels max |
| Using manual sharing for systematic access | Manual shares are deleted on ownership change; cannot be audited at scale | Use sharing rules or Apex managed sharing |
| Creating hundreds of sharing rules | Sharing recalculation takes hours; performance degrades; impossible to audit | Redesign role hierarchy or OWD |
| Giving View All / Modify All to bypass sharing issues | Completely bypasses the sharing model; equivalent to admin access on that object | Fix the underlying sharing design |
| Ignoring external OWD | External users may see other companies’ data | Set external OWD separately (usually Private) |
| Not considering LDV impact | Private OWD on 100M+ record objects causes massive share tables | Evaluate sharing set size; consider HVCP sharing sets |
Identity Best Practices
Best Practices
| Practice | Why It Matters |
|---|
| Use the corporate IdP for all internal SSO | Centralizes authentication; enables consistent MFA; simplifies offboarding |
| Use Federation ID for SAML user matching | Decoupled from Salesforce username; survives username changes and org migrations |
| Implement JIT provisioning (custom handler when possible) | Eliminates manual user creation; keeps user attributes synchronized with IdP |
| Always enable MFA for direct login and validate IdP MFA for SSO | Salesforce requires MFA; IdP-based MFA satisfies the requirement for SSO logins |
| Use Named Credentials for all callout authentication | Keeps credentials out of code and version control; platform manages token lifecycle |
| Configure Single Logout for security-sensitive environments | Prevents orphaned sessions; user logs out everywhere when they log out anywhere |
| Grant minimum OAuth scopes | Each scope is an attack surface; “full” scope is rarely needed |
| Rotate Connected App secrets and certificates on a schedule | Limits exposure window if credentials are compromised |
Anti-Patterns
| Anti-Pattern | Risk | Correct Approach |
|---|
| Hardcoding credentials in Apex | Credentials in version control; visible to all developers | Use Named Credentials |
| Using Username-Password OAuth flow | Deprecated by Salesforce; sends credentials in plain text (over TLS, but still risky) | Use JWT Bearer or Client Credentials for S2S |
| Not implementing Single Logout | User logs out of IdP but Salesforce session remains active | Configure SLO in SAML settings |
| Using “full” OAuth scope for all Connected Apps | Over-privileged access; any compromise gives complete access | Grant minimum scopes per integration |
| Skipping MFA “because we have SSO” | SSO without IdP MFA means single-factor authentication | Verify IdP enforces MFA or add Salesforce MFA |
| Multiple SSO configurations without clear routing | Users confused about which login button to use; support burden | Use Login Discovery to route users automatically |
| Not revoking Connected App access when integrations are decommissioned | Dormant access tokens remain valid; zombie integrations | Audit and revoke quarterly |
Permission Model Best Practices
Best Practices
| Practice | Why It Matters |
|---|
| Use Minimum Access Profile pattern | One baseline profile with almost no permissions; layer with Permission Sets |
| Create atomic Permission Sets (one function per PS) | “Create Quotes” not “Sales User Everything” — enables mix-and-match |
| Bundle with Permission Set Groups for role assignment | Groups represent business roles; individual PS represent capabilities |
| Use Muting Permission Sets for exceptions | Remove specific permissions without duplicating Permission Sets |
| Never grant View All / Modify All unless absolutely necessary | Bypasses entire sharing model; equivalent to admin access on that object |
| Separate UI concerns from security | Page layouts control presentation; FLS controls access. Never use page layouts as security |
| Audit permissions quarterly | Permission creep is real; unused Permission Sets accumulate; FLS drifts |
| Use Permission Set Assignment Expiration for temporary access | Auto-removes access after a specified date; prevents permanent temporary access |
Anti-Patterns
| Anti-Pattern | Risk | Correct Approach |
|---|
| Cloning profiles for each new role | Profile sprawl; impossible to audit; changes must be made across all clones | Minimum Access + Permission Set Groups |
| Managing FLS on profiles | FLS changes affect all users on that profile; cannot grant different FLS to same profile | Manage FLS via Permission Sets |
| Using page layout to “hide” sensitive fields | Users can see hidden fields via reports, API, list views | Use FLS to truly restrict field access |
| Granting System Administrator profile to integration users | Full admin access for integrations; no audit trail of what permissions are actually used | Create integration user profile with minimum access + specific Permission Sets |
| Using “Modify All Data” permission as a shortcut | Bypasses all security; any security model becomes meaningless | Grant specific object permissions |
| Not distinguishing between tab visibility and object access | Hiding a tab does not prevent record access | Use FLS and object permissions for security; tabs for UI convenience |
Encryption Best Practices
Best Practices
| Practice | Why It Matters |
|---|
| Encrypt only what regulations require | Encryption has significant functionality trade-offs; over-encrypting breaks features |
| Do a full impact analysis before encrypting any field | Identify every report, query, formula, and integration that uses the field |
| Use deterministic encryption when searchability is required | Allows exact-match filtering while maintaining encryption at rest |
| Start with Salesforce-managed keys unless regulation requires otherwise | Simplest to manage; BYOK and cache-only add operational complexity |
| Test extensively in sandbox before production | Encryption changes are difficult to reverse; validate all functionality |
| Document which fields are encrypted and why | Future administrators need to understand the encryption rationale |
Anti-Patterns
| Anti-Pattern | Risk | Correct Approach |
|---|
| Encrypting everything “for extra security” | Breaks search, sorting, reporting, formulas; massive functional regression | Encrypt only regulated fields |
| Using probabilistic when deterministic is needed | Users cannot search or filter on the field; workflow rules may break | Choose scheme based on functional requirements |
| Not testing encrypted field impact on reports | Reports that filter or sort on encrypted fields fail silently | Test every report that references encrypted fields |
| Enabling encryption without a key rotation plan | Stale keys increase risk; compliance audits require rotation evidence | Establish key rotation cadence before go-live |
| Forgetting to encrypt the search index | Encrypted field values may appear in the search index unencrypted | Enable search index encryption alongside field encryption |
Portal Security Best Practices
Best Practices
| Practice | Why It Matters |
|---|
| Set External OWD to Private for most objects | Default assumption — external users should not see other companies’ data |
| Audit guest user profile quarterly | Guest user permissions creep; Salesforce tightens rules regularly |
| Use Sharing Sets for HVCP users instead of sharing rules | Sharing Sets are optimized for high volume; sharing rules don’t apply to HVCP |
| Test with each external license type | Different licenses have different sharing behaviors; verify each one |
| Remove all unnecessary object permissions from guest user | Guest users should have explicit opt-in access only |
| Never expose PII to guest users | Data breach risk for unauthenticated visitors |
| Use “Secure guest user record access” setting | Ensures records created by guest users are owned by the site’s default owner |
Anti-Patterns
| Anti-Pattern | Risk | Correct Approach |
|---|
| Using same OWD for internal and external | External users may see data from other companies | Set External OWD separately |
| Giving guest users API access | Unauthenticated API access enables data scraping | Disable guest API access unless specifically justified |
| Using Customer Community Plus when Community suffices | Unnecessary cost; adds role hierarchy complexity | Start with Community; upgrade only if reporting/hierarchy needed |
| Not testing implicit sharing for portal users | Portal users may see parent Account data unintentionally | Audit implicit sharing paths for each external user type |
| Sharing too broadly via Sharing Sets | Records from one customer’s Account visible to another customer | Use the narrowest possible lookup match |
Programmatic Security Best Practices
Best Practices
| Practice | Why It Matters |
|---|
Default to with sharing on all Apex classes | Enforces the running user’s sharing model; secure by default |
Use USER_MODE for SOQL and DML | Enforces CRUD + FLS + sharing comprehensively |
| Always use bind variables in SOQL | Prevents SOQL injection; parameterized queries |
| Use Named Credentials for all callouts | Keeps secrets out of code; platform manages authentication |
| Never log sensitive data (PII, credentials, tokens) | Logs are accessible to admins; may be exported |
Use inherited sharing for utility classes | Safe default that inherits the caller’s context |
Document every without sharing usage | Each bypass must be justified and reviewed |
Anti-Patterns
| Anti-Pattern | Risk | Correct Approach |
|---|
| No sharing keyword on Apex classes | Defaults to without sharing; bypasses sharing model silently | Always specify with sharing or inherited sharing |
| Using string concatenation in SOQL | SOQL injection vulnerability | Use bind variables or String.escapeSingleQuotes() |
| Trusting page layout to hide fields (no FLS check in Apex) | API access bypasses page layouts; users see all fields | Enforce FLS with USER_MODE or stripInaccessible() |
| Storing OAuth tokens in Custom Settings/Custom Metadata | Visible to all admins; in version control | Use Named Credentials |
Using without sharing on controllers | All users see all records regardless of sharing model | Use with sharing on controllers; without sharing only in narrow service methods |
Security Architecture Review Checklist
Use this visual checklist when reviewing any CTA scenario to ensure you have addressed every layer of the security model.
flowchart LR
subgraph "Layer 1: Authentication"
L1A["SSO / IdP\nConfiguration"]
L1B["MFA\nEnforcement"]
L1C["Login Policies\n(IP, hours)"]
end
subgraph "Layer 2: Authorization"
L2A["Object CRUD\n(Profiles + PS)"]
L2B["FLS\n(Permission Sets)"]
L2C["Record Access\n(OWD + Sharing)"]
end
subgraph "Layer 3: Data Protection"
L3A["Platform\nEncryption"]
L3B["Data Masking\n(Formula fields)"]
L3C["Audit Trail\n(FAT + Event Mon.)"]
end
subgraph "Layer 4: Integration Security"
L4A["Named\nCredentials"]
L4B["OAuth Flow\nSelection"]
L4C["Token\nPolicies"]
end
L1A --> L2A --> L3A --> L4A
L1B --> L2B --> L3B --> L4B
L1C --> L2C --> L3C --> L4C
style L1A fill:#1565c0,color:#fff
style L1B fill:#1565c0,color:#fff
style L1C fill:#1565c0,color:#fff
style L2A fill:#2e7d32,color:#fff
style L2B fill:#2e7d32,color:#fff
style L2C fill:#2e7d32,color:#fff
style L3A fill:#e65100,color:#fff
style L3B fill:#e65100,color:#fff
style L3C fill:#e65100,color:#fff
style L4A fill:#4a148c,color:#fff
style L4B fill:#4a148c,color:#fff
style L4C fill:#4a148c,color:#fff
Governance Best Practices
| Practice | Description | Frequency |
|---|
| Security Health Check | Run Salesforce Health Check; address all critical/high findings | Monthly |
| Permission audit | Review all profiles, Permission Sets, and Permission Set Groups | Quarterly |
| Sharing rule review | Verify all sharing rules are still needed; remove obsolete rules | Quarterly |
| Guest user audit | Review guest user profile, sharing rules, and accessible data | Quarterly |
| Connected App audit | Review all Connected Apps; revoke unused integrations | Quarterly |
| Encryption key rotation | Rotate encryption keys per compliance requirements | Per policy (annually minimum) |
| Event Monitoring review | Review login anomalies, data export events, API patterns | Weekly/Monthly |
| User deprovisioning | Verify SSO-deprovisioned users are deactivated in Salesforce | Automated or weekly |
Sources