Apex runs in system context. As such, the CRUD and FLS restrictions of the current user are not honored. This is outlined very briefly here:
ISVs that wish to get their app listed on the AppExchange must pass a security review. It has now become mandatory for developers to code their application to honor the CRUD and FLS constraints of the currently running user on both reads and writes. The burden that this imposes upon an Apex code base is unreasonable.
This Idea is to have the platform provide an 'automatic' facility for enforcing CRUD/FLS in Apex that meets the security requirements of the security review team. This Idea is NOT about arguing the merits of whether CRUD/FLS enforcement should be required.
We've heard various rebuttals from Salesforce about this feature over the past years. They all go something like this:
- "The ISV should honor the security settings of the administrator of the org." Again, this is not the point of this Idea; This Idea is about providing an automatic way for CRUD/FLS to be enforced without writing layers and layers of abstraction around SOQL and DML to use the aforementioned access check methods that Apex currently provides. The related Ideas below call attention to the tedious nature of using them
- "Apex sometimes needs to run in system mode so we can't enforce CRUD/FLS automatically". This is a red herring. There are a dozen different ways to implement this without eliminating the ability to run in system mode when necessary. A few of those ideas are discussed below.
- "Every application is different so it's up to the application developer to figure out the appropriate security architecure". Again, this is about the fact that the burden of using the methods provided in Apex today is unreasonable. Adding 100s of isCreatable(), isAccessible(), etc. checks is onerous and easily circumvented intentionally or inadvertently by a developer.
- "Sometimes you just want to Update the fields that you have FLS access to" -- This is a very narrow use case -- Transactional applications want an all-or-nothing outcome. They can't be satisfied with "well, I updated 8 of the fields on that records and lost all of the updates on the other 2 fields the user supplied"
- "If you just use Visualforce inputField and a Standard Controller, this is all handled automatically" Lightning Components have no such analog. This further increases the barrier for adoption of Lightning Components.
Enforcing CRUD/FLS could be handled in a few different ways:
- Provide something similar to the "with sharing" keyword that each Apex class can be decorated with to indicate that all SOQL and DML executed from that class implicitly honors CRUD/FLS
- Provide overloaded versions of Database.query, Database.insert, Database.upsert and Database.delete that allow a caller to specify CRUD/FLS enforcement. This should be an API versioned change so that future API versions enforce this behavior by default and it must be explicitly disabled (back to system mode)
- Provide a database access layer that allows a custom implementation of CRUD/FLS logic for an application. The fact that SObjects can't be subclassed to provide this functionality means that you have to write 'helper' classes that must be explicitly called (and can be overlooked). Visualforce provides bindings to SObject fields so that locale is considered when rendering -- if you dream up your own access layer using custom Apex classes, you immediately lose a lot Visualforce goodness -- not to mention issues with Heap size, overall code performance, etc.
Apex should be "secure by default", not "insecure by default".