You're partway through an access review and someone asks the question that should be easy: who can see this field? In Salesforce, answering it for a single field means reconstructing field-level security across every profile and every permission set in the org — and the platform gives you no one place to look.
It's a fair question with a genuinely awkward answer. Here's the manual way, the faster query, and how to get it in one screen.
The manual way: Setup, one grantor at a time
Field-level security lives on each grantor, not on the field. So to see who can read or edit Account.Region__c, you open each grantor and look:
- Setup → Profiles → a profile → Object Settings → Account → find Region → check Read Access and Edit Access.
- Then again through Setup → Permission Sets → each set → Object Settings → Account → Region.
It works, and for one field on a small org it's tolerable. But the cost scales with the number of grantors, not the number of fields you care about: a mature org has dozens of profiles and permission sets, and you're opening every one to answer a question about a single field. Miss one and your audit is wrong in the quiet direction — the direction nobody notices until it matters.
The faster way: query FieldPermissions
Field-level security is queryable, and one statement beats the click-through. The FieldPermissions object holds a row for every grantor that can see a field:
SELECT Parent.Label, Parent.Type, Parent.Profile.Name,
PermissionsRead, PermissionsEdit
FROM FieldPermissions
WHERE SobjectType = 'Account'
AND Field = 'Account.Region__c'
A few things make this query make sense:
- Every row is a permission set. The
Parentof aFieldPermissionsrecord is aPermissionSet. Profiles don't store FLS directly — each profile owns an auto-created permission set, so a profile's grant shows up as a row whereParent.Type = 'Profile'andParent.Profile.Nameis the profile's name. Permission sets you built show up asParent.Type = 'Regular'. - A row exists only where read is granted.
FieldPermissionsrecords positive grants. If a grantor isn't in the results, it has no explicit FLS for that field, and access falls back to the org's defaults. (You also can't havePermissionsEditwithoutPermissionsRead.) - Run it in the Developer Console or any SOQL client. Swap the
SobjectTypeandFieldfor the field you're auditing — note thatFielduses theObject.Fieldform, not just the field name.
This is the method most senior admins reach for, and it's the right one. Its limits are the predictable ones: it's per field, you run it again for the next field, and it doesn't expand permission set groups for you. A group's access is the union of its component sets minus any muting, which you reconstruct by hand from these rows.
Who can see this field? — should be a lookup, not an investigation.
Seeing it in one place
Once your org's metadata is in SchemaForce, this stops being a query you write and becomes a panel you read. Every field's page has a field-level security section — who can see and edit this field — with two lists: Visible to and Editable by. Each entry is a profile, permission set, or permission set group, and each links to that grantor's full access, so you can go from "who can see this field" to "what else does that profile grant" in a click. Groups are resolved for you: their effective access is computed as the union of the component sets minus muting, so you read the real outcome, not the raw composition.
It's the same answer the SOQL gives you — assembled across every grantor at once, and kept current as the org changes.
What this tells you — and what it doesn't
Be precise about the grain, because access reviews live or die on it. This is configured field-level security at the profile, permission set, and permission set group level — not "which named users can see the field." User-level effective access (assignments, the role hierarchy, ownership, sharing) is a separate question, and neither the SOQL above nor the panel answers it. Fields with no explicit FLS follow the org's defaults rather than appearing in either list.
And as everywhere here, it's metadata only — object and field definitions and the permission records that govern them, never the contents of a record. You get the full who-can-see picture without any access to the data inside the field.
The next time an access review lands on your desk, "who can see this field?" should take a glance, not an afternoon — whether you run the query yourself or read it off the field.



