Forgot 'with sharing': Every User Could See Everything
“Wrote an Apex class without the sharing keyword. Every user bypassed all sharing rules. Full org access.”
What Happened
Built a custom Apex controller for a Visualforce page at a Cloud Nimbus client. Forgot to add 'with sharing' to the class declaration. In Apex, if you don't specify sharing, it defaults to 'without sharing' in many contexts — meaning the running user bypasses all sharing rules, role hierarchy, and org-wide defaults. A sales rep discovered they could see every Opportunity in the org, including ones belonging to other teams and regions. The client's VP of Sales called me directly. That was not a fun call.
The Wrong Way
// No sharing keyword = without sharing behavior
public class OpportunityController {
@AuraEnabled
public static List<Opportunity> getOpportunities() {
// This returns ALL Opportunities in the org
// regardless of the user's sharing rules,
// role hierarchy, or OWD settings.
return [SELECT Id, Name, Amount, StageName
FROM Opportunity
ORDER BY Amount DESC
LIMIT 100];
}
// Every user sees every deal. Including
// competitors' pricing your reps shouldn't see.
}The Right Way
// ALWAYS declare sharing explicitly
public with sharing class OpportunityController {
@AuraEnabled
public static List<Opportunity> getOpportunities() {
// "with sharing" enforces the running user's
// sharing rules, role hierarchy, and OWD.
// Users only see records they have access to.
return [SELECT Id, Name, Amount, StageName
FROM Opportunity
ORDER BY Amount DESC
LIMIT 100];
}
}
// Use "without sharing" ONLY when you intentionally
// need to bypass sharing (e.g., a system process
// that needs full access). Document WHY.
// "inherited sharing" for utility classes that
// should respect the caller's sharing context.The Lesson
Always declare sharing explicitly. 'with sharing' by default. 'without sharing' only with a comment explaining why. 'inherited sharing' for utility classes. Never leave it unspecified.
Enjoyed this? Get more like it.
Glen's Musings — AI, investing, and building things. Occasional. Free.
More Security Mistakes
String Concatenation in SOQL: Hello, Injection
Built a dynamic SOQL query with string concatenation from user input. Textbook injection vulnerability.
Read morePainfulGave Everyone 'Modify All' Because It Fixed the Bug
Users couldn't edit records. I gave the profile 'Modify All Data' instead of fixing the actual sharing rules.
Read morePainfulAPI Keys Hardcoded in Apex: Now in Version Control Forever
Hardcoded an API key in an Apex class. Committed to Git. Deployed to prod. Key visible to every developer.
Read more