The Salesforce security model is not a single switch — it is a layered system of access controls that work together to ensure users see exactly the records and fields they are supposed to, and nothing more. Understanding each layer and how they interact is fundamental to every implementation, regardless of cloud or industry.
The four layers of Salesforce security
Salesforce security operates across four distinct dimensions. Each one answers a different question about access.
Organisation level — who can log into the org? Managed through IP restrictions, login hours, two-factor authentication and My Domain policies.
Object level — which objects can a user see, create, edit or delete? Managed through Profiles and Permission Sets.
Record level — which specific records within an accessible object can a user see? Managed through OWD, the role hierarchy, sharing rules, manual sharing and Apex managed sharing.
Field level — which fields within an accessible record can a user see or edit? Managed through Field-Level Security on Profiles and Permission Sets.
Getting any one of these wrong produces either a security vulnerability (too much access) or a broken user experience (too little access). The layers interact — you cannot fix record-level exposure with field-level restrictions.
Org-Wide Defaults — the security foundation
OWD is the single most important security decision in any Salesforce implementation. It sets the most restrictive possible access for each object — the floor that no other setting can go below.
The three standard settings for most objects are Private, Public Read Only and Public Read/Write. Private means users can only see records they own. Public Read Only means all users can see all records but only owners can edit. Public Read/Write means all users can view and edit all records.
The critical rule: all other sharing mechanisms can only open access beyond OWD, never restrict it. If Account is set to Public Read/Write, there is no sharing rule or profile setting that prevents a user from seeing another user’s Account records. This is why getting OWD right before go-live matters enormously — changing OWD on a large object with millions of records can trigger a sharing recalculation that takes hours.
Profiles and Permission Sets
Profiles control object-level and field-level access. Every user must have exactly one Profile. Permission Sets are additive — they can only grant access that the Profile has not already granted. A user can have many Permission Sets.
The best practice in mature orgs is a minimum-access Profile (often called a base Profile or Minimum Access Profile) combined with Permission Sets that grant specific access for specific roles. This avoids the anti-pattern of maintaining dozens of nearly-identical profiles.
In Summer ‘26 the new Field Access tab in Object Manager shows all field permissions across all profiles and permission sets in one view — a significant improvement over the previous approach of opening each profile individually.
The role hierarchy
The role hierarchy grants record access upwards. A user in a higher role can see all records owned by users below them in the hierarchy. This implicit sharing requires no configuration beyond setting up the hierarchy.
For custom objects, the Grant Access Using Hierarchies checkbox on the org-wide default switches this off. Standard objects always grant access through the hierarchy, so a sensitive standard-object record needs a Private OWD plus deliberately narrow sharing rules rather than a hierarchy setting.
Sharing rules
Sharing rules extend access to groups of users beyond what OWD allows. Ownership-based rules share records owned by one public group or role with another. Criteria-based rules share records matching specific field conditions — for example, sharing all Opportunities with Stage = Closed Won with the Finance team.
Every sharing rule requires a From group and a To group, and specifies whether the grant is Read Only or Read/Write. There is no way to create a sharing rule that restricts access.
Apex managed sharing
When declarative sharing rules cannot express the required logic, Apex
managed sharing fills the gap. You insert records into the Share object
for the relevant SObject — AccountShare, OpportunityShare or
MyObject__Share for custom objects.
// Grant Read access to an Account for a specific user
AccountShare share = new AccountShare();
share.AccountId = accountId;
share.UserOrGroupId = userId;
share.AccountAccessLevel = 'Read';
share.OpportunityAccessLevel = 'None';
share.CaseAccessLevel = 'None';
share.RowCause = Schema.AccountShare.RowCause.Manual;
insert share;
Use a custom Apex sharing reason (rather than Manual) when your
sharing logic should survive profile-level sharing recalculations and
be distinguishable from user-initiated manual shares.
Summer ‘26 security changes (API v67.0)
The most impactful Summer ‘26 change for security is the Apex sharing
default. From API v67.0 a class with no with sharing / without sharing / inherited sharing keyword runs with sharing, so its SOQL
enforces the running user’s org-wide defaults, sharing rules and manual
shares.
The common belief that “no keyword used to mean without sharing” is
only partly right. On v66.0 and earlier the default depended on how the
transaction started: Aura controllers and @AuraEnabled methods called
from LWC already ran with sharing; Visualforce controllers, Apex REST
services, asynchronous classes and every other entry point ran without sharing. A class with no keyword also takes the sharing mode of the
class that called it. So the classes that change behaviour on a version
bump are the second group — REST services, batch and queueable classes,
invocable methods and Visualforce controllers — not LWC controllers.
Two other v67.0 changes land at the same time: database operations run
in user mode by default (object and field permissions enforced), and
WITH SECURITY_ENFORCED no longer compiles. The
Apex security guide
covers all three; the
v67 migration scenario
covers what breaks and how to fix it.
Before raising any class to API v67.0, add an explicit sharing keyword, decide each query’s access mode deliberately, and run the tests as a restricted user. Code that returned every record may now return a subset — silently.
The security review checklist
Before go-live, verify these for every object in scope:
- OWD set to the most restrictive appropriate setting
- Role hierarchy reflects the real reporting structure
- Sharing rules cover all legitimate cross-team access needs
- Profiles grant minimum necessary object permissions
- Permission Sets cover role-specific access beyond the base profile
- FLS restricts sensitive fields from users who should not see them
- Apex classes have explicit sharing declarations
- No class relies on an omitted sharing keyword; every class states
with,withoutorinherited sharing
Test your knowledge — Security & Sharing
10 questions · Basic to Advanced