1

We are building a application which required a Public Custom Metadata Type. We have a Screen flow which has an LWC Component which calls an Aura Enabled Method of a public with sharing class. In this method we are querying the Custom Metadata Type record. The problem is that a user who don't have access to the Custom Metadata Type record is able to access the Records as a query result.

As mentioned in this link and this link:

  1. Restrict access to custom metadata types is enabled by default.

  2. I have removed the Customize Application and View Setup and Configuration permissions in Profile.

  3. I have added WITH SECURITY_ENFORCED keyword to the Query.

  4. I have checked the using the DescribeSObject Result

Boolean isMetadataAccessible =((SObject)Type.forName('','metadataname').newInstance()).getSObjectType().getDescribe().isAccessible();

The isAccessible() function is returning true.

Still the user is able to access the Custom Metadata Type Record.

In this link, it is mentioned that the with sharing modifier in the Apex class, doesn’t affect query behavior such as, isAccessible() and isCreatable().

Does it mean the apex query will not throw any error if user doesn't have access to Custom Metadata Type Record? or

How to restrict user by accessing the Custom Metadata Type Record?

7
  • 2
    Is there actually a problem with the custom metadata type records being read by the code? It is normal that this is used to hold configuration and should thus be readable regardless of user permissions. Recall that you manage these records through Setup, and thus only certain types of user can do so. Additionally, you cannot programmatically update custom metadata type records using normal DML and must use the Apex Metadata API to do so (and that requires appropriate code to be developed). Can you explain why you care about permissions here?
    – Phil W
    Dec 7, 2023 at 15:18
  • Hi @PhilW, Actually we want our application to be published on AppExchange so does this cause any problem with the security review as we haven't added the WITH SECURITY_ENFORCED to the SOQL query and we didn't check the security aspects. "It is normal that this is used to hold configuration and should thus be readable regardless of user permissions." Does this mean regardless of whatever permission the user has, the soql query will always returns the Custom Metadata Record?
    – S1th
    Dec 7, 2023 at 15:22
  • 1
    No. CMTs are intended to hold configuration for your app, so having these read is not a problem (and you should not bother with "WITH SECURITY_ENFORCED" which, BTW, is replaced by [WITH USER_MODE]). Add a comment on the end of the first line of code for the query, or even use Your__mdt.getInstance() to retrieve the record(s). Final point, the way you used Type and newInstance is inefficient. If you can do this statically, do so: Your__mdt.SObjectType.getDescribe().isAccessible()
    – Phil W
    Dec 7, 2023 at 15:26
  • The comment on the end of the line thing is a way to add "self documenting false positive" explanations in your code to reduce the effort of recording false positives. See this answer for more detail.
    – Phil W
    Dec 7, 2023 at 15:29
  • 2
    I meant "No, this will not cause a problem with the AppExchange security review"... as long as you follow appropriate processes and either use the getInstance route or mark the SOQL as a false positive. It's worth being aware of the API version sensitivity of isAccessible() btw. Note the point around before and after version 54.
    – Phil W
    Dec 7, 2023 at 15:40

1 Answer 1

3

Custom Metadata Types are intended to hold configuration for your app, so having these read is not a problem (and you should not bother with "WITH SECURITY_ENFORCED" which, BTW, is replaced by WITH USER_MODE).

When possible obtain your CMT records using one of the Your__mdt.getInstance methods, but if you do need to use SOQL (e.g. to get a long text area field value), then simply mark the end of the first line of the statement that includes the query with a "self documenting false positive explanation" comment. Take a look at this earlier Q&A for more detail.

The only time this may lead to an issue would be if you exposed a sensitive value (e.g. client secret or PII data) in the UI to the user; that's not something you should typically be doing using CMT records anyway (e.g. a client secret would simply be used in Apex to make a callout, not be shown to the user).

NB:

  • The way you used Type and newInstance is inefficient. If you can do this statically, do so like Your__mdt.SObjectType.getDescribe().isAccessible().
  • Note the behaviour change at version 54 for isAccessible() as per the documentation.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .