Salesforce Summer ’26 Apex Security Overhaul — Are Your Orgs Ready?

If you haven’t touched your API version in a while, Summer ’26 is about to force the issue.

Starting with Summer ’26 (API v67.0), any Apex class deployed at the new API version runs under a completely different security model by default. Database operations now execute in user mode instead of system mode. Sharing rules are enforced automatically. And WITH SECURITY_ENFORCED, the clause thousands of orgs rely on to check field- and object-level security, is being removed as a language construct.

This is not a minor patch note. It is a default-behavior change that can silently break production logic the moment a class gets redeployed at v67 or later.

What actually changed

Three things happen simultaneously when a class targets API v67.0 or higher:

Apex database operations default to user mode. Previously, Apex ran in system mode unless you explicitly declared with sharing. Now, DML and SOQL respect the running user’s object and field permissions unless you explicitly opt into system mode with without sharing or the new System.AccessLevel parameter on database methods.

Classes enforce sharing by default. A class with no sharing declaration used to run in system mode, ignoring the org’s sharing rules entirely. At v67, the absence of a declaration now behaves like with sharing. Any integration class, batch job, or utility class you never bothered to annotate is affected.

WITH SECURITY_ENFORCED is removed. This SOQL clause, added years ago as a stopgap for field-level security checks, no longer exists as valid syntax. Salesforce wants you on Security.stripInaccessible() or the new AccessLevel.USER_MODE parameter instead.

Triggers always run in system mode. This one cuts the other way — regardless of the API version, triggers are unaffected by the user-mode default and continue running with full object access, matching prior behavior.

Why this breaks things you don’t expect

The danger isn’t in code that already has with sharing and proper FLS checks. It’s in the code nobody has opened in three years.

Picture a batch class written in 2019, no sharing declaration, quietly querying and updating records across the org because system mode never asked permission. Redeploy that class after bumping to v67, and it inherits sharing enforcement it was never designed for. Records the running user can’t see disappear from queries. Updates that used to succeed now fail with an insufficient access exception, or worse, silently skip rows if you’re not checking DML results.

Integration users are especially exposed. Many integration users are deliberately scoped with limited permission sets, on the assumption that Apex running in system mode would handle the heavy lifting regardless. Flip that class to user mode and the integration user’s actual permissions suddenly matter.

What to do before you touch the API version

Before bumping any class to v67 or later, audit every class without an explicit with sharing or without sharing declaration. There is no safe default anymore, so be explicit everywhere.

Search your codebase for WITH SECURITY_ENFORCED and replace it. For SOQL, migrate to:

List<Account> accounts = [
    SELECT Id, Name, Industry
    FROM Account
    WITH USER_MODE
];

For DML, use the AccessLevel parameter directly on database methods:

Database.insert(newAccounts, AccessLevel.USER_MODE);
Database.update(existingAccounts, AccessLevel.SYSTEM_MODE);

Test integration and batch jobs against the actual permission sets of the users or integration accounts that run them, not just an admin profile in your sandbox. A test class that runs as System Administrator will not catch a sharing-rule regression.

Finally, don’t bump API versions org-wide as a batch operation. Migrate class by class, run your full regression suite after each change, and watch debug logs for INSUFFICIENT_ACCESS_OR_READONLY errors during UAT.

The bigger picture

This is Salesforce closing a gap that security researchers have flagged for years: too much Apex ran with implicit, unchecked system-level access, and too many developers treated WITH SECURITY_ENFORCED as a checkbox rather than a real control. Summer ’26 forces explicit intent. That’s a net positive for platform security, but it means the migration cost lands on every org carrying legacy code.

If your org’s classes were written before sharing-by-default was even a consideration, budget real time for this. Don’t discover it in production.


Have you hit unexpected sharing errors after a Summer ’26 upgrade? Share what broke in the comments — it’ll help the next admin who hasn’t gotten there yet.

Leave a Reply

Your email address will not be published.