Share
Salesforce Winter ’27 Security Enforcements: Five Technical Fixes Before Quiet Failures Reach Production
Salesforce states that the Profile Filtering setting is enabled by default and enforced in Winter ’27, and the release reached production in three scheduled waves on September 4, October 2, and October 9. Salesforce Ben’s go-live guide also lists a new Use Any API Auth requirement for SOAP API login() among the updates enforced with the release. The first of those changes can break automation without throwing any error at all, which is exactly what a recent live demo showed.
Saman Attar, Senior Software Engineer at F5 and Founder of CampApex.org, joined Matt Meyers, CTA, CoFounder and CEO of EzProtect, on Salesforce Security Office Hours to break a sandbox on purpose and fix it live. The five points below pair what that demo showed with what Salesforce documents, so you can separate published platform behavior from observed behavior when you test your own org.
1. Profile Filtering changes what a profile reference returns for any user but the running user
The release update says profile filtering prevents users from viewing profile names other than their own unless they hold the View All Profiles permission. Salesforce first shipped the update in Summer ’26 and enforces it in Winter ’27 across Lightning Experience and Salesforce Classic. The release update tells admins to grant View All Profiles before enforcement only to users whose role requires every profile name.
The running user’s own profile stays visible. Salesforce documents the $Profile global variable as information about the current user’s profile, so a formula that checks $Profile.Name evaluates the same way after enforcement. The exposure sits in traversals that read someone else’s profile, such as Owner, then Profile, then Name. Tom Bassett’s Winter ’27 prep guide flags exactly that path and lists validation rules, flows, assignment rules, approval processes, sharing rules, Apex classes, LWC, Aura, reports, list views, custom metadata, custom settings, and formula fields as metadata to scan.
2. Eight permissions bypass the filter, so a test run from an admin login proves nothing
View All Profiles is only one way past the filter. Salesforce’s profile filtering article states that Customize Application, Manage Users, Manage Profiles and Permission Sets, Create and Set Up Experiences, Manage Customer Users, Manage External Users, and Delegated External User Administrator also allow a user to view all profiles. The same article lists contexts that still expose profile names, including the Setup Audit Trail for users with View Setup and Configuration and the delegated administration screens.
A sandbox test run under any login that holds one of these permissions will pass while the same code path fails for a sales or service user. Saman’s first rule in the session was to test as an end user and never as a system administrator. Use System.runAs with a user built on a minimum access profile in your Apex tests, and audit the permission sets on every integration and test user for the eight permissions before you trust a green run.
3. The failures surface as exceptions, blank values, or nothing at all
Saman enabled Profile Filtering in a sandbox and ran three automations that each read another user’s profile name. The behavior below is what the demo showed, because Salesforce has not published how Profile Filtering affects Apex, formula, or validation rule evaluation.
An Apex validation that filtered a User query on Profile.Name and then read the first row stopped returning its custom error. The query came back empty for a running user who could no longer see that profile name, and indexing into the empty list threw a list index exception. A simplified version of the pattern looks like this.
// Simplified illustration of the demo pattern
List<User> owners = [
SELECT Id FROM User
WHERE Id = :rec.OwnerId AND Profile.Name = ‘Integration User’
];
Id integrationOwnerId = owners[0].Id; // throws a ListException when the list is empty
A formula field that displayed the creator’s profile name rendered blank on records created by other users. A validation rule that compared the owner’s profile name with a literal value stopped firing entirely, because the profile name no longer resolved for the running user and the comparison evaluated false, so the record saved without any warning. Saman pointed out that a blocked user at least notices the problem, while nobody notices a rule that has stopped firing.
The demo also touched Apex access modes. The Apex Developer Guide states that Apex runs in user context by default in API version 67.0 and later, while API version 66.0 and earlier default to system mode, and that WITH USER_MODE and WITH SYSTEM_MODE set the mode per query. Salesforce has not documented how Profile Filtering interacts with either mode, so test each class at the API version it is saved under instead of assuming one result covers your codebase.
4. Custom permissions answer the right question, while View All Profiles answers it for everyone
Granting View All Profiles restores a broken automation in one step and widens profile visibility for every user who receives it. Tom Bassett treats it as a fallback option because the release update exists to restrict that visibility. The temptation is real in most orgs, since only 20 percent of organizations in the 2026 SF Ben admin survey reported very effective enforcement of least privilege.
The fix Saman demonstrated replaces the profile name check with a custom permission assigned through a permission set. In declarative logic, the $Permission global variable references the current user’s custom permission access, so a validation rule condition such as NOT($Permission.Bypass_Owner_Validation) replaces the profile comparison. In Apex, the FeatureManagement class provides checkPermission(apiName), which returns whether a named custom permission is enabled.
if (FeatureManagement.checkPermission(‘Bypass_Owner_Validation’)) {
return;
}
Both checks evaluate the running user, and that detail decides whether the swap is safe. A rule that asks about the person saving the record translates directly into a custom permission. A rule that asks about the record owner or creator does not, because no custom permission check evaluates another user, so that logic needs a redesign rather than a one-line replacement.
Build the inventory before you change anything. Tom Bassett recommends pulling a local metadata copy with Salesforce DX and searching it, and a plain text search across a retrieved project catches most of the traversals.
grep -rn “Profile.Name” force-app/main/default
Saman also showed how Salesforce MCP and the Tooling API can search metadata across an org, which helps when components live outside your source repository.
5. Authentication enforcement continues on separate dates after the release lands
The SOAP change lands with the release. The login() reference states that use of login() is restricted to users with the Use Any API Auth permission and that attempts without it fail with an INSUFFICIENT_ACCESS error. The same page confirms that Salesforce retires login() in the Summer ’27 release, that it remains available in API version 64.0 and earlier, and that it is disabled by default for orgs created in Winter ’26 and later.
The OAuth changes follow separate dates. Salesforce’s architect guidance for Winter ’27 states that production refresh tokens expire after 30 days of inactivity starting November 4, 2026, that the OAuth 2.0 device flow is restricted beginning November 30, 2026, and that the username-password, user-agent, and hybrid user-agent flows retire on February 20, 2027. The same guidance says support for connected apps ends by Summer ’27 and that external client apps use a default-closed security posture. Salesforce’s admin release blog notes that App Manager now includes a Migrate to External Client App action.
Saman recommended the client credentials flow for integrations that still pass a username and password. To find them, filter Login History for the OauthUsernamePassword login subtype as described in the SF Ben prep guide, and remember that Login History covers only six months. Tom Bassett’s session made the same point, because an integration that runs quarterly may never appear in that window.
An inventory protects your org better than any single permission grant
Retrieve your metadata, list every reference to another user’s profile, and test each code path with System.runAs under a minimum access user. Replace the checks that concern the running user with custom permissions, redesign the checks that concern the owner, and grant View All Profiles only where a role genuinely needs every profile name. Then reconcile Login History against your connected apps, assign Use Any API Auth only to the integration users that still call login(), and check your instance on the Salesforce maintenance calendar to confirm which of these dates has already passed.
Watch Saman’s full session to see each failure and each fix in a live sandbox, and pair it with Tom Bassett’s breakdown of the authentication changes.
Register for the next session of Security Office Hours and bring your toughest Salesforce security questions for Matt Meyers and his guests to answer live.
Share
Did you love this blog and wish there could be more?
It is our goal to keep you informed about everything you need to know about Salesforce security to keep your Salesforce data and company safe and secure by providing you with the highest quality of original content.
If this sounds good to you, then sign-up below to be one of the first to know when the next super awesome Salesforce security blog has been released.

