Andy in the Cloud

From BBC Basic to Force.com and beyond…


1 Comment

What does the new Apex User Mode Default mean for you?

Since I started with Salesforce some 15+ years ago, as part of a team building the first account app on AppExchange, security has always been an important consideration. Coming from other platforms, the principle of least privilege was also instilled in me. While Salesforce has always had a flexible set of security controls, they weren’t enforced “by default” in Apex code – giving it access to everything. This has now changed with these two Summer’26 / API 67.0 changes for CRUD security and sharing security, marking one of the biggest design shifts for Apex since its inception! The trouble with this of course – is literally millions and millions of lines of Apex code has been written against the exact opposite assumption.

So what’s going to happen once you upgrade to Summer’26 / API 67.0?

Firstly you don’t have to upgrade to API 67.0 straight away and quite often I have seem teams lag a little bit to take on the work in planned way or just wait to see if its stable. But once you do make the move, to be realistic, despite explicit Apex trigger code being exempt (by design they remain in system mode), you cannot assume the rest of your Apex code is not going to break. When it does, you will probably find yourself having a number of painful but “good” security design reflections. The good news is that, depending on how recent your codebase is, you might already be partway on the journey! There is a lot more to be written, reflected, tooled up etc on this topic. For now in this blog, I want to discuss what paths you might find yourself on and what to be thinking about.

How much Apex breaks depends on whether you’ve been using either the new declarative-based Apex user and system modes or sticking with the old method of manually performing CRUD checks. If you’ve applied either, you should also have started using Permission Set in your solution. Permission Sets are key to this adoption. By applying both these approaches in deployments and during test execution (via System.runAs), you’re not only enforcing security but also providing admins with ready-to-use permission configurations that match your entire codes needs or, if desired, a more granular breakdown by module or groups of actions users are permitted to perform. Below, we will first explore this optimistic adoption path and then discuss the more challenging one.

Before we dive in here is a short summary table of paths that you might fall into:

Path A:

Fully applied:

– Apex User Mode
– System Mode
– “without sharing”
Path B:

Partially applied:

– Apex User Mode fully
– Or Apex Describe Checks
– Or “with sharing”, some “without sharing”
Path C:

No Security Checks:

– Possibly no Permission Sets


If this is exclusively the case across your code base – well done! This falls into the best happy path of all – and aligns with Salesforce guidance on system mode. Don’t assume all is well though, plan accordingly, use this as an opportunity to review your Permission Set strategy (see over-permissioning below) and double check without sharing usage with System Mode. *You are in a good starting position, and should have some created some Permission Sets to support your code, but still might need to check those and also check any system mode scenarios. Then apply system mode and/or without sharing annotations. See further guidance below.Depending on the size of your codebase this could be a significant bit of work depending on your approach to permission sets and use of state flags, calc fields and hidden/app only objects. Resist diving into this by simply creating a quick fix huge permission set for all fields, objects required. See further guidance below.

* The requirement to also use “without sharing” with System Mode did catch me out – its not parity with User Mode, it does not require “with sharing” per documentation and in fact overrides class level sharing.

Ok, so I have already been embracing Apex User Mode now what? (Path B)

In short, if this is the case, your journey has already started, and you’re either already done (unlikely tbh) or have some work left to do. If you have been using user mode in your DML or SOQL code, you will have noticed that the Apex runtime (by design) throws errors when fields or DML operations are not accessible—because the users profile (or ideally, permission set) has not granted such access. This can occur not only when end users run your code but also during Apex tests.

Security exceptions in Apex tests are as valid as they are for end users without permissions. They are designed to prompt you to create dynamic test users in your Apex code, assign your permission sets, and leverage System.runAs to ensure the tests run successfully from a permissions perspective – failure is a bug in your code or permission set. This setup is effective, and code paths using it will function “as is” under the new user mode default.

However, in places you may have opted not to use user mode because the code needs to act on a flag, computed field or object need by your code but not the user. In these cases, simply not using user mode did used to default to the Apex system mode, which can lead to failures with the new user mode default. First, do not add such fields/objects to permission sets unless the rationale has changed; they are still system mode access scenarios. Instead, elevate permissions to system mode explicitly by using the explicit SYTEM_MODE flag/clause in Apex/SOQL. The same applies to classes where you have also not specified without sharing. In short, be as explicit about system mode now as you have been about user mode and you will heading in a good direction.

What is user mode? I have not been adding security enforcement in my code… (Path C)

Firstly, you might have historically thought that your code runs in user mode simply because the user executes it, which is true. However, unlike the Lightning UI, which removes fields, makes them read-only, or hides records, Apex has not followed suit to date. It does not generate errors, atomically clear variables, or block inserts. This means your custom UIs may display information to which they should not have access, and they could also allow updates or deletions that should not be permitted. It’s possible that you are reading this and thinking that it’s just a small team in a small organization, and you don’t really care. While that may have been a pragmatic approach in the past, in today’s world of increasing security exploits, it’s not a strategy you can continue to embrace – on any platform. Salesforce, although challenging here, is providing you with a necessary wake-up call.

So, what should you do to prepare? A simple but not holistic step is to repeatedly run your Apex code and tests against API 67.0 to identify any issues as you update assigned profiles/permission sets. However, keep in mind that this may not provide complete coverage, so performing end-user UX testing is also likely going to be important. This is a basic approach will help you pinpoint which objects and fields users need access to. But what is also crucial, is to ask what types (or roles) of users you are supporting and what actions they perform. Without this understanding, you might fall into the trap of over-permissioning, which involves creating and assigning a permission set with access to every object and field in your object model and others.

Over-permissioning is a trap because, unless your solution is very simple, the data a user type needs access to (for a specific subset of features) will likely differ from the entire data set or the data your code requires to function properly. For instance, users can then inadvertently edit calculated fields or related objects (like logs, rollups, and state flags) outside of your code if given access. Therefore, it’s important to delineate user types (roles/personas), their actions, and how those actions relate to the essential objects and fields for business functionality versus those necessary solely for managing the application, often termed system-level. The same principle applies to sharing rules: if code requires visibility over all rows but users do not, this must be acknowledged as well.

For a more holistic view I do recommend using various org dependency inspection tools alongside running tests to map out which objects and fields are utilized by specific Apex classes, as well as the code paths of those classes, and how those relate to each user type’s required actions. Note this will not help with dynamically referenced fields and objects. Overall though this will help you design a solid Permission Set strategy that is effectively a manifestation of your apps features and security design.

Closing thoughts… for now

If you have a sizable codebase that’s fairly old, you’re certainly reading this with your head in your hands, wondering where to get started. While you can defer upgrading to API 67.0, it cannot be done indefinitely. I know it’s a lot to manage, but please try to avoid the trap of over-permissioning. It’s an easy fix, but keep in mind that you will also expose all those objects and fields through standard Salesforce interfaces, Lightning Experience, List Views, Dashboards, Reports, etc. Even if such fields and objects are not on layouts, they can still be accessed by end users.

There is certainly some tooling that will help with all of this by combining dependency data among classes, objects and fields to help uncover the super set of objects/fields in scope, this at least would be a good start. Such tooling is something I might explore but likely best served by others building such tools already to expand into. For sure Salesforce Security Scanner / PMD rules will also need to be updated – which I assume is in the pipeline. I will likely follow up with further thoughts on this topic – so let me know your thoughts. Also if you want to connect with me meanwhile to discuss your situation feel free to find me on LinkedIn.


21 Comments

Creating, Assigning and Checking Custom Permissions

I have been wanting to explore Custom Permissions for a little while now, since they are now GA in Winter’15 i thought its about time i got stuck in. Profiles, Permission Sets have until recently, been focusing on granting permissions to entities only known to the platform, such as objects, fields, Apex classes and Visualforce pages. In most cases these platform entities map to a specific feature in your application you want to provide permission to access.

However there are cases where this is not always that simple. For example consider a Visualforce page you that controls a given process in your application, it has three buttons on it Run, Clear History and Reset. You can control access to the page itself, but how do you control access to the three buttons? What you need is to be able to teach Permission Sets and Profiles about your application functionality, enter Custom Permissions!

CustomPermissions
CustomPermission

NOTE: That you can also define dependencies between your Custom Permissions, for example Clear History and Reset permissions might be dependent on a Manage Important Process  custom permission in your package.

Once these have been created, you can reference them in your packaged Permission Sets and since they are packaged themselves, they can also be referenced by admins managing your application in a subscriber org.

SetCustomPermissions

The next step is to make your code react to these custom permissions being assigned or not.

New Global Variable $Permission

You can use the $Permission from a Visualforce page or as SFDCWizard points out here from Validation Rules! Here is the Visualforce page example given by Salesforce in their documentation.

<apex:pageBlock rendered="{!$Permission.canSeeExecutiveData}">
   <!-- Executive Data Here -->
</apex:pageBlock>

Referencing Custom Permissions from Apex

IMPORTANT UPDATE: Since API 41 (Winter’18) there is now a native way to read Custom Permissions. The following may still be useful if you have requirements not met by the native method. FeatureManagement.checkPermission.

In the case of object and field level permissions, the Apex Describe API can be used to determine if an object or field is available and for what purpose, read or edit for example. This is not going help us here, as custom permissions are not related to any specific object or field. The solution is to leverage the Permission Set Object API to query the SetupEntityAccess and CustomPermission records for Permission Sets or Profiles that are assigned to the current user.

The following SOQL snippets are from the CustomPermissionsReader class i created to help with reading Custom Permissions in Apex (more on this later). As you can see you need to run two SOQL statements to get what you need. The first to get the Id’s the second to query if the user actually has been assigned a Permission Set with them in.


List<CustomPermission> customPermissions =
    [SELECT Id, DeveloperName
       FROM CustomPermission
       WHERE NamespacePrefix = :namespacePrefix];

List<SetupEntityAccess> setupEntities =
    [SELECT SetupEntityId
       FROM SetupEntityAccess
       WHERE SetupEntityId in :customPermissionNamesById.keySet() AND
             ParentId IN (SELECT PermissionSetId
                FROM PermissionSetAssignment
                WHERE AssigneeId = :UserInfo.getUserId())];

Now personally i don’t find this approach that appealing for general use, firstly the Permission Set object relationships are quite hard to get your head around and secondly we get charged by the platform to determine security through the SOQL governor. As a good member of the Salesforce community I of course turned my dislike into an Idea “Native Apex support for Custom Permissions” and posted it here to recommend Salesforce include a native class for reading these, similar to Custom Labels for example.

Introducing CustomPermissionReader

In the meantime I have set about creating an Apex class to help make querying and using Custom Permissions easier. Such a class might one day be replaced if my Idea becomes a reality or maybe its internal implementation just gets improved. One things for sure, i’d much rather use it for now than seed implicit SOQL’s throughout a code base!

Its pretty straight forward to use, construct it in one of two ways, depending if you want all non-namespaced Custom Permissions or if your developing a AppExchange package, give it any one of your packaged Custom Objects and it will ensure that it only ever reads the Custom Permissions associated with your package.

You can download the code and test for CustomPermissionsReader here.


// Default constructor scope is all Custom Permissions in the default namespace
CustomPermissionsReader cpr = new CustomPermissionsReader();
Boolean hasPermissionForReset = cpr.hasPermission('Reset');

// Alternative constructor scope is Custom Permissions that share the
//   same namespace as the custom object
CustomPermissionsReader cpr = new CustomPermissionsReader(MyPackagedObject.SObjectType);
Boolean hasPermissionForReset = cpr.hasPermission('Reset');

Like any use of SOQL we must think in a bulkified way, indeed its likely that for average to complex peaces of functionality you may want to check at least two or more custom permissions once you get started with them. As such its not really good practice to make single queries in each case.

For this reason the CustomPermissionsReader was written to load all applicable Custom Permissions and act as kind of cache. In the next example you’ll see how i’ve leveraged the Application class concept from the Apex Enterprise Patterns conventions to make it a singleton for the duration of the Apex execution context.

Here is an example of an Apex test that creates a PermissionSet, adds the Custom Permission and assigns it to the running user to confirm the Custom Permission was granted.

	@IsTest
	private static void testCustomPermissionAssigned() {

		// Create PermissionSet with Custom Permission and assign to test user
		PermissionSet ps = new PermissionSet();
		ps.Name = 'Test';
		ps.Label = 'Test';
		insert ps;
		SetupEntityAccess sea = new SetupEntityAccess();
		sea.ParentId = ps.Id;
		sea.SetupEntityId = [select Id from CustomPermission where DeveloperName = 'Reset'][0].Id;
		insert sea;
		PermissionSetAssignment psa = new PermissionSetAssignment();
		psa.AssigneeId = UserInfo.getUserId();
		psa.PermissionSetId = ps.Id;
		insert psa;

		// Create reader
		CustomPermissionsReader cpr = new CustomPermissionsReader();

		// Assert the CustomPermissionsReader confirms custom permission assigned
		System.assertEquals(true, cpr.hasPermission('Reset'));
	}

Seperation of Concerns and Custom Permissions

Those of you familiar with using Apex Enterprise Patterns might be wondering where checking Custom Permission fits in terms of separation of concerns and the layers the patterns promote.

The answer is at the very least in or below the Service Layer, enforcing any kind of security is the responsibility of the Service layer and callers of it are within their rights to assume it is checked. Especially if you have chosen to expose your Service layer as your application API.

This doesn’t mean however you cannot improve your user experience by using it from within Apex Controllers,  Visualforce pages or @RemoteAction methods to control the visibility of related UI components, no point in teasing the end user!

Integrating CustomerPermissionsReader into your Application class

The following code uses the Application class concept i introduced last year and at Dreamforce 2014, which is a single place to access your application scope concepts, such as factories for selectors, domain and service class implementations (it also has a big role to play when mocking).

public class Application {

	/**
	 * Expoeses typed representation of the Applications Custom Permissions
	 **/
	public static final PermissionsFactory Permissions = new PermissionsFactory();

	/**
	 * Class provides a typed representation of an Applications Custom Permissions
	 **/
	public class PermissionsFactory extends CustomPermissionsReader
	{
		public Boolean Reset { get { return hasPermission('Reset'); } }
	}
}

This approach ensures their is only one instance of the CustomPermissionsReader per Apex Execution context and also through the properties it exposes gives a compiler checked way of referencing the Custom Permissions, making it easier for application developers code to access them.

if(Application.Permissions.Reset)
{
  // Do something to do with Reset...
}

Finally, as a future possibility, this approach gives a nice injection point for mocking the status of Custom Permissions in your Apex Unit tests, rather than having to go through the trouble of setting up a Permission Set and assigning it in your test code every time as shown above.

Call to Action: Ideas to Upvote

While writing this blog I created one Idea and came across a two others, i’d like to call you the reader to action on! Please take a look and of course only if you agree its a good one, give it the benefit of your much needed up vote!

 


9 Comments

Permission Sets and Packaging

Permission Sets have been giving me and an unlucky few who are unable to install my Declarative Rollup Summary Tool some headaches since i introduced them. Thankfully I’ve recently discovered why and thought it worth sharing along with some other best practices i have adopted around packaging permission sets since…

Package install failures due to Permission Sets

After including Permission Sets in my package, I found that some users where failing to install the package, they received via email, the following type of error (numbers in brackets tended to differ).

Your requested install failed. Please try this again.
None of the data or setup information in your salesforce.com organization should have been 
 affected by this error.
If this error persists, contact salesforce.com Support through your normal channels
 and reference number: 604940119-57161 (929381962)

It was frustrating that i could not help them decode this message, it required them to raise a Salesforce support case and pass their org ID and error codes on the case. For those that did this, it became apparent after several instances, a theme was developing, a package platform feature dependency!

Normally such things surface in the install UI for the user to review and resolve. Dependencies also appear when you click the View Dependencies button prior to uploading your package. However it seems that Salesforce is currently not quite so smart in the area of Permission Sets and dependency management, as these are hidden from both!

Basically i had inadvertently packaged dependencies to features like Ideas and Streaming API via including my Permission Sets, one of which i had chosen to enable the Author Apex permission. This system permission seems to enable a lot of other permissions as well as enabling other object permissions (including optional features like Ideas, which happened to be enabled in my packaging org). Then during package install if for historic reasons the subscriber org didn’t have these features enabled the rather unhelpful error above occurs!

Scrubbing my Permission Sets

I decided enough was enough and wanted to eradicate any Salesforce standard permission from my packaged Permission Sets. This was harder than i thought, since simply editing the .permissionset file and uploading it didn’t not remove anything (this approach is only suitable for changing or adding permissions within a permission set).

Next having removed entries from the .permissionset file, i went into the Permission Set UI within the packaging org and set about un-ticking everything not related to my objects, classes and pages. This soon became quite an undertaking and i wanted to be sure. I then recalled that Permission Sets are cool because they have an Object API!

I started to use the following queries in the Developer Console to view and delete on mass anything i didn’t want, now i was sure i had removed any traces of any potentially dangerous and hidden dependencies that would block my package installs. I obtained the Permission Set ID below from the URL when browsing it in the UI.

select Id, SobjectType, PermissionsCreate, PermissionsEdit, PermissionsDelete, PermissionsRead
  from ObjectPermissions where ParentId = '0PSb0000000HT5A'
select Id, SobjectType, Field
  from FieldPermissions where ParentId = '0PSb0000000HT5A'

CheckObjectPermissions

Note that System Permissions (such as Author Apex) which are shown in the UI, currently don’t have an Object API, so you cannot validate them via SOQL. However at least these are listed on a single page so are easier to check visually.

Lessons learned so far…

So here are a few lessons i’ve learned to date around using Permission Sets…

  • Don’t enable System Permissions unless your 100% sure what other permissions they enable!
  • When editing your .permissionset files don’t assume entries you remove will be removed from the org.
  • Use SOQL to query your Permission Sets to check they are exactly what you want before uploading your package
  • Don’t make your Permission Sets based on a specific User License type (this is covered in the Salesforce docs but i thought worth a reminder here as it cannot be undone).
  • Do design your Permission Sets based on feature and function and not based on user roles (which are less likely to match your perception of the role from one subscriber to another). Doing the former will reduce the chances of admins cloning your Permission Sets and loosing out on them being upgraded in the future as your package evolves.