access & permissions 29 October 2026

the profile creep nobody talks about

salesforce has eleven permission types. your admin uses three of them.

The companies, people and numbers in the scenarios below are illustrative composites of common situations. They are not real cases or measured results. Anything presented as data names its source.

A RevOps lead at a mid-market SaaS company inherited a Salesforce admin role in late 2024. The previous admin had left six months earlier. The org had been running without a dedicated admin during the gap, with minor issues handled by a Salesforce consultant on retainer.

Within two weeks of starting, the new admin ran a permission audit. The audit found the following state. The org had 73 Profiles. Many of them appeared to serve overlapping purposes, “Sales Rep” and “Sales Representative” and “SalesRep” and “Standard Sales User.” Nobody on the current team could explain why each of the four existed or what distinguished them.

The org had 340 Permission Sets, with varying levels of adoption. Some were used by hundreds of users. Some were used by two. A meaningful fraction were used by zero.

The org had 180 Permission Set Groups, organizing the permission sets in ways that were themselves overlapping. Several groups contained most of the same permission sets as other groups.

The org had 45 custom Sharing Rules, many of which referenced criteria that no longer applied (role hierarchy positions that had been reorganized, record types that had been deprecated).

The org had a dozen active Queues, several of which hadn’t received a record in years.

And across all of this, the admin could not cleanly answer the question “what does a specific user have access to?” for any given user. The effective permission set was the union of the user’s Profile, their Permission Sets, their Permission Set Groups, their Role, the Sharing Rules that applied, the Queues they were in, plus any manual sharing that had been done on specific records.

This is the permission labyrinth inside a mature Salesforce org. The complexity of Salesforce’s permission model, combined with years of additive configuration, produces an access graph that nobody can read in its entirety.

This essay is about that labyrinth. Why Salesforce permissions are structurally harder than other permission systems, how they accumulate over time, and what to do about the mess.

the Salesforce permission model is eleven mechanisms deep

Salesforce has, depending on how you count, roughly eleven distinct mechanisms for granting access to data. These include Profiles (the base permission set for a user), Permission Sets (additional permissions layered on top), Permission Set Groups (bundles of permission sets), Roles (used for record-level sharing through the role hierarchy), Public Groups (used for manual sharing), Queues (used for assigning records to a group), Sharing Rules (used for automated record-level sharing), Manual Sharing (ad-hoc record-level sharing), Apex Sharing (programmatic sharing), Territory Hierarchy (used for territory-based sharing), and Organization-Wide Defaults (the baseline sharing setting for each object).

A user’s effective access to a given record is computed across all of these mechanisms. The computation follows specific rules, most of which are “the most permissive grant wins”, if any mechanism grants access, the user has access, regardless of other mechanisms being restrictive.

The complexity of this model is not accidental. It evolved to handle every possible enterprise sharing pattern across the twenty-five years Salesforce has been operating. The model can express almost any access control policy. It can also express an unreadable mess, which is what happens when multiple admins, each making reasonable changes over years, layer their configurations without rationalization.

The typical mid-market Salesforce org, after five to ten years of operation, has an access graph that no single person can fully explain. The various mechanisms overlap, sometimes redundantly, sometimes in subtle ways that produce unintended grants.

some of the layers that decide what a Salesforce user can do

  • profilethe base set of permissions
  • permission setsadded on top, one by one
  • permission set groupsbundles of permission sets
  • role hierarchywho sees whose records
  • sharing rulesexceptions to the defaults
  • public groupsused by sharing rules
  • org-wide defaultsthe baseline visibility
  • manual sharingone record at a time
Each layer is reasonable on its own. Together they make a user's real access hard to read in one place.

the default pattern is accretion

Salesforce permissions accumulate for the same reasons permissions accumulate everywhere: each individual change is reasonable and easier to add than to replace, and nothing triggers removal.

A specific request comes in: “Can Jane see these additional fields?” The admin has several options. Modify Jane’s Profile (which affects everyone on the Profile). Create a new Permission Set and assign it to Jane (which affects only Jane and anyone else assigned to the set). Modify the Field Level Security on Jane’s Profile (narrow, but affects everyone on the Profile). Create a manual share on the specific records Jane needs (very narrow, but doesn’t scale).

The easy answer, in practice, is to create a new Permission Set. Permission Sets are designed for this, layered permissions that supplement the base Profile. Creating a Permission Set takes a few minutes. Assigning it to Jane takes less. The request is resolved quickly.

Three months later, a similar request comes in. Bob needs access to a specific list view and the related records behind it. The admin creates another Permission Set for Bob.

Six months later, a different team lead asks for their team to have a capability. The admin, seeing that Permission Sets are the pattern, creates a new Permission Set for the team and assigns it to all team members.

Over five years, this pattern produces hundreds of Permission Sets. Some are narrow (one person, one specific grant). Some are broad (a team of twenty people, a bundle of permissions). The naming conventions vary based on which admin created them. The documentation varies based on how much the admin felt like writing at the time.

Separately, the Profiles multiply. Every time a significantly new role emerges in the company, an admin creates a new Profile. The old Profile doesn’t get decommissioned, because people still have it. The new Profile is slightly different from the old one, and the differences are not always clearly documented.

Separately, the Sharing Rules expand. Every time a new sharing requirement emerges, this team needs to see these records, this group needs access to this region, a new Sharing Rule is created. The old rules stay.

The cumulative state is that the org has every permission mechanism populated with years of accreted configurations, and the effective permission of any given user is the sum of their Profile plus all their Permission Sets plus their Permission Set Groups plus whatever Sharing Rules apply to them plus their Role plus any manual shares, computed through the rules of the platform.

nobody can read it in its entirety

The specific consequence is that the permission state is unreadable. Not unreadable for a single user in isolation, tools exist to report on a single user’s effective access. Unreadable in aggregate, across the user base, as a design.

An admin asked “what does our access model allow?” cannot answer. The answer is distributed across eleven mechanisms, each with its own configurations, interacting through rules that are well-documented but not intuitively traceable.

The practical consequence is that access reviews, which ostensibly validate the state of the access model, have to work with partial views. The review might look at Profile assignments and Permission Set assignments per user, which is what the standard access review reports produce. The review typically doesn’t cross-reference Sharing Rules, Queue memberships, Role-based sharing, and manual sharing, because surfacing all of those in one review is a custom development effort that most companies haven’t done.

This means the access review is looking at a subset of the permission state. The reviewer signs off on what they see. What they don’t see, which might include significant residual grants, is not signed off or removed.

the profile consolidation that never happens

A specific anti-pattern: the Profile that was created as a one-off and became a standard.

Example: an admin was asked to grant a specific capability to one person. Instead of adding a Permission Set, they created a clone of the person’s existing Profile, with the added capability baked in. The person was moved to the new Profile.

A month later, another request came in that required similar capabilities. The admin cloned the new Profile again, with additional tweaks, and created yet another Profile.

Over years, this pattern produces a proliferation of Profiles that differ from each other in small, often-undocumented ways. The Profiles accumulate without any cleanup, because consolidating them would require understanding the differences between them and making deliberate decisions to keep or discard each one.

Most admins don’t do this consolidation. The cost of getting it wrong is high, breaking someone’s access is a visible, user-impacting incident. The cost of leaving the sprawl alone is low in the short term.

The specific Salesforce best practice, published for years, is to have few Profiles (usually fewer than ten) and many Permission Sets. Profiles define baseline identity; Permission Sets layer specific capabilities. This keeps the Profile count manageable and moves the permission variation to the Permission Set layer.

Real-world orgs often have the inverse pattern. Dozens of Profiles. Hundreds of Permission Sets. Both layers are doing similar work redundantly, and neither is clean.

the integration users are the highest-privilege accounts

A specific category of Salesforce account worth isolating: the integration user.

An integration user is a Salesforce account used by an external system to interact with Salesforce through the API. The typical integration pattern: the external system needs to read and write Salesforce data. It authenticates as an integration user. Its actions are attributed to the user.

Integration users typically have broad permissions, because the external system’s actions need to cover a wide range of operations. A marketing automation platform might need to create leads, update contacts, run campaigns, report on opportunities. The integration user has the permissions to do all of these.

In many orgs, the integration user has a System Administrator profile. This is the expedient choice, give the integration the admin profile, and it can do whatever it needs. The alternative, crafting a narrow permission set for the specific integration, requires understanding the integration’s actual needs and implementing them, which is more work.

The integration user with System Administrator profile is, effectively, a standing admin credential for the external system. Anything that compromises the external system compromises Salesforce at the admin level.

The specific exposure: a marketing automation platform’s credentials are stored somewhere in the marketing automation platform. If the platform is breached, the Salesforce credentials are exposed. If the Salesforce credentials give System Administrator, the breach gives Salesforce admin.

The fix is to use narrow permission sets for integrations. Each integration gets a profile/permission set combination that grants only what the integration actually needs. This requires understanding the integration’s operations, which is more work than just using System Administrator, which is why most companies use System Administrator.

Auditing integration users is a specific exercise. Identify them in the user list (they’re usually labeled or named conventionally). Check each one’s profile. Any integration user with System Administrator is a candidate for permission narrowing.

the sandbox and production drift

Salesforce orgs typically have multiple environments: production, developer sandboxes, partial copy sandboxes, full copy sandboxes. Each is a separate instance with its own user accounts and configuration.

Permission changes are supposed to be managed through a deployment pipeline, changes are made in a sandbox, tested, and deployed to production. In practice, emergency changes are often made directly in production. Over time, production configuration drifts from sandbox configuration.

The drift is rarely reconciled. Each sandbox is refreshed from production periodically (not always), which brings production drift back to the sandboxes. The sandboxes’ own configurations (created for testing purposes) may or may not survive refresh.

The specific identity exposure: user accounts exist in sandboxes that don’t exist in production. Developer sandboxes often have permissive configurations that wouldn’t be acceptable in production. Data in sandboxes is often a copy of production data, with production-level sensitivity.

A sandbox with permissive access and real production data is a specific risk. Anyone with sandbox access has access to the production-sensitivity data, without the production-level controls. This is often overlooked because sandboxes are considered “not production.”

Auditing sandbox access should be part of the Salesforce identity program. Who has access to sandboxes? What data do the sandboxes contain? What permissions do sandbox users hold?

the exercise

Here is the specific Salesforce identity audit.

Pull the list of users in your production Salesforce org. For each user, pull their Profile, Permission Sets, Permission Set Groups, Role, and Public Group memberships.

Identify users who are no longer active employees. Deactivate them if they haven’t been already. Check that deactivation has propagated (Salesforce deactivation doesn’t delete the user, which is appropriate, but it should prevent login).

For active users, review their Profile assignment. Is the Profile appropriate for their current role? If the Profile name or description doesn’t match the role, the assignment is suspect.

Review Permission Set assignments. For each Permission Set assigned to significant user populations, check whether the Permission Set is documented and whether the current assignments match the intent. Remove assignments that aren’t justified.

Audit integration users specifically. Identify which external systems are authenticating as which Salesforce users. For each integration user with System Administrator, document the business case and investigate whether narrower permissions are feasible.

Audit Sharing Rules. Look for rules that reference obsolete Roles, obsolete Public Groups, or obsolete Record Types. Remove rules that no longer apply.

Audit Profiles. Count them. If the count is over ten, you have Profile sprawl. Identify the top candidates for consolidation and consolidate them.

Audit Queues. Identify Queues that haven’t received a record in the last year. Retire them.

Review the sandboxes. For each sandbox, identify who has access and whether they should. Sandbox access tends to be forgotten; cleaning it up recovers audit hygiene.

This is a multi-day exercise for a mature org with significant accretion. The subsequent quarterly check-ins are smaller.

Salesforce is the system that holds your customer data, your pipeline, your revenue forecasting. It’s one of the most sensitive systems in a B2B company. The permission model is one of the most complex in enterprise software. The combination produces a permission state that nobody can read and nobody has cleaned up in years.

Clean it up. Or it will be what’s exposed in the next credential compromise or insider incident.

access creep · every two weeks

One mechanism, one practical step.