How is "Deny Unless" Different From "Allow If" for Access Controls (ACLs)?

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
01-17-2025 08:11 AM
The Certified Application Developer (CAD) Delta Exam Study Guide here discusses two different "Decision Types" for Access Controls (ACLs), as follows:
But I must be missing something, because these seem like exactly the same thing to me. Example:
I am going to DENY you dessert UNLESS you eat your vegetables.
I am going to ALLOW you to have dessert IF you eat your vegetables.
What is the difference? I don't get it. Documentation here
- 3,194 Views
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-23-2025 07:31 PM
I like how Jason Nichols explains it in this video: https://www.youtube.com/watch?v=Zl1DyGSLkTQ. TodT had it right in this thread, but I'll explain it another way:
It has more to do with the specific implementation of Deny-Unless ACLs rather than the semantics. From that semantic perspective, there is no difference. But putting it into practice with the ServiceNow data model is another matter.
Take this example: you want to restrict the visibility of incidents from VIPs in the platform to just those users with the itil_admin role. Out of box you might have two ACLs that provide access to the incident table for all records, perhaps one for users with the role of itil and another for users with the role of incident_read. If I want to restrict access to VIP records, I can't simply add a new ACL with the role and the condition, because I already have the other ACLs that grant access! So in order to make it work with the existing Allow-If ACLs, I have to go in to each of them to modify the condition to first filter out non-VIP incidents. What that looks like is the following:
- For non-VIP incidents, if you have the itil role, grant access
- For non-VIP incidents, if you have the incident_read role, grant access
- For VIP incidents, if you have the itil_admin role, grant access
Only using Allow-If ACLs unfortunately means you have to modify all of them to get an explicit deny based on your use case. BUT if you use Deny-Unless ACLs (which are evaluated first, and if they fail, deny access outright), then you do not need to modify the existing ACLs. This is fantastic for avoiding any potential security oversight or modifications to out of box records. Deny-Unless ACLs would look like this:
- For VIP incidents, you can't see the record UNLESS you have the itil_admin role
- For all incidents, if you have the incident_read role, grant access
- For all incidents, if you have the itil role, grant access
In this case, the system will first evaluate ACL #1 and fail if the user does not have the itil_admin role. No need to modify the others, as they are not checked if the Deny-Unless rule fails. ACLs #2 and #3 are not evaluated. In this case, it is an explicit rejection of access, as opposed to an implicit one with only Allow-If ACLs.
This might work too with the veggie example taken literally. Imagine I didn't want you to eat a slice of a pie I baked up unless you ate your broccoli. But I also still said you can have dessert if you eat your vegetables. In this case, I've laid out two "Allow-If" statements:
- If you eat your vegetables, you can have dessert
- If you eat your broccoli, you can have pie
If you really hated broccoli, but still wanted dessert, you could just eat your carrots instead, pass the first condition, and run away with your slice of pie. The statements do not contradict one another, and unfortunately I would have to modify my first "Allow-If" statement to something like "if you eat any vegetable (except broccoli) then you can have dessert)". So instead, I modify my statements to include some "Deny-Unless" language, like the following:
- Unless you eat your broccoli, you can't have any pie
- If you eat your vegetables, you can have dessert
If you don't pass my first condition, you can't go to the second. That's an explicit deny, and good use of the "Deny-Unless" principal. And to actually get the pie, I have to satisfy both the "Deny-Unless" AND the "Allow-If" conditions.
This has some pretty big implications if you've worked in the ServiceNow security model for a while. Prior to "Deny-Unless" ACLs, I can't tell you how many times I've advised a customer to consider the entire set of existing ACLs when implementing a new security condition, and how often that advice was ignored. One new ACL that defines a requirement doesn't work if another one lets me in. Worse yet, a new version of ServiceNow or the installation of a new application could bring in additional ACLs and throw the whole thing into question if an ACL pops in an grants access even when everything else has been modified to support the original use case. I've heard before "hey, I thought we locked this down, why can users see this data now?" Well, a new ACL was introduced that wasn't configured to exclude the data you wanted to hide, and now it is exposed to the users that passed that ACL check.
Another metaphor I like to use is the key to house model. Allow-If rules are like a door with a lock that fits many different kinds of keys. If I don't have one type of key (i.e. role, condition, or script=true), that's okay, I'll try another until I find one that works. Deny-Unless rules are like a strict security system that requires a specific passcode and zaps me if I get if I get it wrong once. But even if I get the passcode right, I still need one of those keys to get in, which is how ACLs work with Allow-If rules being checked after Deny-Unless.
You might ask why the entire model isn't Deny-Unless by default, and that has more to do with the nature of the original permissions model as supporting use cases where the focus was on granting access instead of rejecting it. If you had itil, or incident_read, or admin, then you were able to see incident data. This helped to speed up implementation by defining who should see data as opposed to trying to define who shouldn't. There are certainly considerations for each type of ACL, but it really boils down to using Allow-If rules to grant access and Deny-Unless rules to deny access more explicitly and without modification to other existing rules. It's a huge time saver for implementations and extensions of existing platform capability.
Hopefully that breakdown helped, I'm very happy with the new Deny-Unless rules since they've made it easier to manage security model customizations and give peace of mind for the longevity of any particular security requirement.