Install
$ agentstack add skill-clientell-ai-salesforce-skills-sf-permissions ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Salesforce Permission Management & Access Auditing
You are a Salesforce permissions specialist. Manage permission sets, audit access, diagnose permission errors, and enforce least-privilege security.
1. Permission Model Overview
| Layer | Controls | Scope | |-------|----------|-------| | Profiles | Login hours, IP ranges, page layouts, record types, default app | One per user (required) | | Permission Sets | Object CRUD, FLS, Apex class, VF page, tab, custom permissions | Many per user (additive) | | Permission Set Groups | Bundle of Permission Sets + optional muting | Many per user (additive) |
Best practice: Minimal Profile + Permission Sets. Assign a stripped-down profile (e.g., "Minimum Access - Salesforce") and grant everything else through Permission Sets and Permission Set Groups.
Why Permission Sets over Profiles:
- A user can have only ONE profile but MANY permission sets
- Permission sets are additive and composable
- Profiles cause merge conflicts in source control
- Permission Set Groups enable role-based bundling with muting for exceptions
- Salesforce is actively moving away from profile-based permissions
2. Permission Set XML (SFDX Source Format)
Order Manager
Full CRUD on Order__c, read on Account
false
Salesforce
Order__c
true
false
true
true
false
true
Order__c.Amount__c
true
true
Order__c
Visible
OrderService
true
OrderEntryPage
true
Bypass_Validation
true
RunReports
true
hasActivationRequired: Whentrue, must be activated in a session before taking effectlicense: Restricts assignment to users with that license type- Object permissions hierarchy: Read required for Edit; Edit required for Delete;
viewAllRecords/modifyAllRecordsoverride sharing
3. Permission Set Group XML
Sales Team
All permissions needed by sales reps
Updated
Account_Reader
Opportunity_Manager
Report_Viewer
Sales_Team_Muting
Muting Permission Set
A muting permission set removes specific permissions from the group. It only works inside a Permission Set Group.
Sales Team Muting
Removes delete access granted by Opportunity_Manager
Opportunity
true
Muting revokes the permission only for users who get access through this group. Direct assignments are unaffected.
4. Profile Metadata
Profiles are still required for: login hours/IP restrictions, page layout assignments, record type defaults, default app assignment.
Minimal Profile Strategy
true
Minimal profile - all access via Permission Sets
Salesforce
480
1080
Account-Account Layout
Avoid putting object/field permissions in profiles. Use profiles only for what cannot be done through permission sets.
5. Object & Field Level Security (CRUD/FLS)
CRUD Permissions Hierarchy
Read ─── required for ──→ Edit ─── required for ──→ Delete
│ │
└── viewAllRecords └── modifyAllRecords
(bypasses sharing) (bypasses sharing + ownership)
FLS (Field-Level Security)
Each field has two flags: Readable and Editable (Editable requires Readable). FLS applies across UI, reports, list views, and API. A field hidden by FLS returns null in SOQL with WITH USER_MODE.
FLS Audit Queries
-- Field permissions for a permission set
SELECT SobjectType, Field, PermissionsRead, PermissionsEdit
FROM FieldPermissions WHERE Parent.Name = 'Order_Manager'
-- Fields a user can edit (across all permission sets)
SELECT SobjectType, Field, PermissionsRead, PermissionsEdit
FROM FieldPermissions WHERE ParentId IN (
SELECT PermissionSetId FROM PermissionSetAssignment
WHERE AssigneeId = '005xx000001234AAA'
)
-- Who can edit a sensitive field?
SELECT Parent.Label, Parent.IsOwnedByProfile
FROM FieldPermissions
WHERE Field = 'Contact.SSN__c' AND PermissionsEdit = true
6. Custom Permissions
Custom permissions are boolean flags to control feature access without modifying code.
Can Export Data
Allows user to export data from custom UI
false
Apex (preferred):
if (FeatureManagement.checkPermission('Can_Export_Data')) {
// user has the custom permission
}
LWC:
import hasExportPermission from '@salesforce/customPermission/Can_Export_Data';
Flow: Use $Permission.Can_Export_Data in Decision elements (returns true/false).
7. Access Auditing
PermissionSetAssignment Queries
-- All users assigned a permission set
SELECT Assignee.Name, Assignee.Username, Assignee.IsActive
FROM PermissionSetAssignment WHERE PermissionSet.Name = 'Order_Manager'
-- All permission sets for a user (excluding profile-based)
SELECT PermissionSet.Label, PermissionSet.Name, PermissionSetGroupId
FROM PermissionSetAssignment
WHERE AssigneeId = '005xx000001234AAA'
AND PermissionSet.IsOwnedByProfile = false
ObjectPermissions Queries
-- Who has Delete on an object?
SELECT Parent.Label, Parent.IsOwnedByProfile,
PermissionsDelete, PermissionsViewAllRecords, PermissionsModifyAllRecords
FROM ObjectPermissions
WHERE SobjectType = 'Account' AND PermissionsDelete = true
-- Over-privileged check: ModifyAll on any object
SELECT Parent.Label, SobjectType FROM ObjectPermissions
WHERE PermissionsModifyAllRecords = true AND Parent.IsOwnedByProfile = false
SetupEntityAccess (Apex/VF/Connected App)
-- Who has access to an Apex class?
SELECT Parent.Label FROM SetupEntityAccess
WHERE SetupEntityType = 'ApexClass'
AND SetupEntityId IN (SELECT Id FROM ApexClass WHERE Name = 'OrderService')
-- Connected App access
SELECT Parent.Label FROM SetupEntityAccess
WHERE SetupEntityType = 'ConnectedApplication'
AND SetupEntityId IN (SELECT Id FROM ConnectedApplication WHERE Name = 'DataLoader')
Permission Set Group Membership
-- Permission sets in a group
SELECT PermissionSetGroup.MasterLabel, PermissionSet.Label
FROM PermissionSetGroupComponent
WHERE PermissionSetGroup.MasterLabel = 'Sales Team'
-- Groups containing a permission set
SELECT PermissionSetGroup.MasterLabel FROM PermissionSetGroupComponent
WHERE PermissionSet.Name = 'Opportunity_Manager'
8. Permission Troubleshooting
INSUFFICIENTACCESSOR_READONLY
User lacks Edit permission on the object or record. Check object-level Edit, sharing access, record ownership, role hierarchy, and record locks (approval process).
SELECT Parent.Label FROM ObjectPermissions
WHERE SobjectType = 'TargetObject__c' AND PermissionsEdit = true
AND ParentId IN (
SELECT PermissionSetId FROM PermissionSetAssignment WHERE AssigneeId = :userId
)
INSUFFICIENTACCESSONCROSSREFERENCE_ENTITY
User lacks access to a related record. Common causes: inserting a child without Read on the parent, changing a lookup to a record the user cannot see, trigger/flow updating a related record.
"Insufficient Privileges" Error
Generic error meaning any of: missing Apex class access, VF page access, Lightning component access, tab visibility, Connected App access, or session-based permission set not activated.
# Quick CLI diagnosis
sf data query -q "SELECT PermissionSet.Label, PermissionSet.Name \
FROM PermissionSetAssignment \
WHERE Assignee.Username = 'user@example.com' \
AND PermissionSet.IsOwnedByProfile = false" --target-org myOrg
9. Sharing vs Permissions
Permissions (CRUD/FLS) and sharing are independent layers:
| Layer | Question | Scope | |-------|----------|-------| | CRUD | Can the user create/read/edit/delete this object type? | Object-wide | | FLS | Can the user see/edit this specific field? | Field-wide | | Sharing | Which specific records can the user access? | Record-level |
A user needs BOTH the right CRUD/FLS permissions AND sharing access.
OWD Settings
| Setting | Effect | |---------|--------| | Private | Only owner + role hierarchy above | | Public Read Only | All users read, only owner edits | | Public Read/Write | All users read and edit | | Controlled by Parent | Determined by parent record (master-detail) |
Record Access Determination Order
1. Record owner? → Full access
2. Above owner in role hierarchy? → Access per OWD
3. Sharing rules? → Read or Read/Write
4. Apex managed sharing? → Read or Read/Write
5. View All / Modify All on object? → Bypasses sharing
6. View All Data / Modify All Data? → Full access
Key Distinctions
viewAllRecords/modifyAllRecordsbypasses sharing for that objectwith sharingin Apex enforces sharing but NOT CRUD/FLSWITH USER_MODEin SOQL enforces both sharing AND CRUD/FLS
10. Gotchas
- Permission Set Groups recalculate asynchronously — changes may take minutes. Check
PermissionSetGroup.StatusforUpdatedvsOutdated. - Profiles cause merge conflicts — profile XML files are enormous and reorder non-deterministically. Prefer permission sets.
- FLS does not restrict API access by default — Apex runs in system mode. Use
WITH USER_MODEorSecurity.stripInaccessible(). - Custom permissions are cached — assignment changes may not reflect until the user re-authenticates.
- Muting permission sets only work inside groups — assigning one directly to a user has no effect.
- Permission set licenses — some require specific licenses. Assignment to users without the license may fail silently.
- Session-based permission sets —
hasActivationRequired=truerequires activation via Flow orSessionPermSetActivation. Not automatic. viewAllRecordsdoes not grant field access — user sees the record but not FLS-restricted fields (when enforced).- IsOwnedByProfile — every profile has a hidden permission set. Filter with
PermissionSet.IsOwnedByProfile = falsein queries. - Assignment limit — maximum 1,000 permission set assignments per user (including group-based).
11. Workflow
Setting Up Permissions for a New Feature
- Identify required access: List objects, fields, Apex classes, VF pages, tabs, and custom permissions.
- Create Permission Set: Generate
.permissionset-meta.xmlwith least-privilege access. - Create Custom Permissions (if needed): Generate
.customPermission-meta.xmlfor feature flags. - Add to Permission Set Group (if applicable): Update
.permissionsetgroup-meta.xml. - Create Muting Permission Set (if needed): Only if the group over-grants for some users.
- Deploy:
``bash sf project deploy start -d force-app/main/default/permissionsets \ -d force-app/main/default/permissionsetgroups \ -d force-app/main/default/customPermissions --target-org myOrg ``
- Assign:
``bash sf org assign permset --name Order_Manager --target-org myOrg sf org assign permsetgroup --name Sales_Team --target-org myOrg ``
- Audit:
``bash sf data query -q "SELECT Assignee.Name, PermissionSet.Label \ FROM PermissionSetAssignment \ WHERE PermissionSet.Name = 'Order_Manager'" --target-org myOrg ``
Migrating from Profile to Permission Sets
- Query all non-default permissions on the profile
- Create equivalent permission sets for each functional area
- Create a Permission Set Group matching the profile's role
- Assign the group to affected users
- Remove permissions from the profile (keep only layout, record type, login hours)
- Validate with audit queries from Section 7
References
- [Permissions Reference](references/permissions-reference.md) — complete Permission Set XML, audit queries, Apex/LWC/Flow permission checks, deployment best practices
- [Governor Limits](../../references/governor-limits.md) — per-transaction limits reference
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Clientell-Ai
- Source: Clientell-Ai/salesforce-skills
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.