Toxic permissions on Salesforce: the combinations that create the risk
A toxic permission is almost never a dangerous privilege taken on its own. It is a combination of privileges that, taken separately, all have a good reason to exist. That is why it survives access reviews.
Definition
A toxic permission is a set of privileges whose combination on a single account enables an action that none of those privileges enabled on its own. On Salesforce, the most common form pairs a broad read privilege, a write or export privilege, and the absence of a control that should have governed both.
The difficulty is not recognising a sensitive privilege — every administrator knows what
Modify All Data does. It is seeing that it coexists, on the same profile,
with API access enabled and without multi-factor authentication. Each element was granted at a
different time, by a different person, for a legitimate reason.
The combinations that come up most often
Full read access + bulk export
View All Data paired with an export privilege — Bulk API, weekly export,
or an exportable report — gives an account the ability to extract the entire customer
data set in a single operation. Neither privilege is abnormal: the first serves
support, the second serves management oversight.
Full write access + API + no MFA
This is the combination most often cited in Salesforce incidents. Modify All
Data and API access on an account that does not require a second factor turn a
compromised credential into full access, with no human interaction and no interface trail.
Integration accounts are particularly exposed: they are granted broad privileges
because they automate, and they are spared MFA for the same reason.
User management + permission set assignment
An account that can create users and assign them permission sets can indirectly grant itself any privilege. This is privilege escalation in the strict sense, and it triggers no native alert.
Guest access and communities
The guest profiles of Experience Cloud sites sometimes inherit object privileges that were never intended for them. A read privilege granted to a guest profile exposes the data to an unauthenticated visitor — that is access control, not site configuration.
Connected apps and dormant OAuth tokens
A connected app authorised two years ago keeps its token for as long as nobody revokes it. The question to ask is not “who has access?” but “which OAuth scopes were granted, to what, and who still uses them?”.
The blind spot
These combinations trigger no native alert. Salesforce permits them all: they are valid configurations. You discover them at the audit, or at the incident.
Why a manual review misses them
An access review looks at privileges profile by profile. Yet a user accumulates one profile and any number of permission sets, each contributing its share. The effective privilege of an account is the sum of those layers, and that sum is displayed nowhere in a usable form.
A mid-sized org has dozens of profiles, hundreds of permission sets and thousands of users. The Cartesian product to be examined exceeds what a quarterly review can cover — and it changes between two reviews.
How to spot them at scale
- Compute the effective privilege per user, by aggregating profile and permission sets — not by reading profiles one by one.
- Look for combinations, not isolated privileges: it is the coming together that creates the risk.
- Cross-reference with authentication status: the same accumulation is benign behind mandatory MFA and critical without it.
- Include non-human accounts — integrations, agents, service accounts. They often carry the broadest privileges and the weakest controls.
- Measure continuously: a combination appears the day someone adds a permission set, not on the day of the audit.
How long does it take to audit an org?
By hand, on an org of a few hundred users, a serious review of effective privileges is counted in days — and it is out of date the next day. Instrumented, the same measurement is replayed at every scan, which shifts the effort from collection to decision.
What should be done with a toxic permission once it has been found?
Rarely remove it outright: it serves a purpose. The useful order is to determine who actually uses it, to cover the risk with a compensating control — mandatory MFA, IP address restriction, reduced OAuth scope — then to withdraw what is no longer in use. That is why a detection tool must remain read-only: the decision to withdraw a privilege in production belongs to the human who knows how it is used.