[object Object]

Auditors do not read ACLs. They read symptoms — the wrong group reading the wrong record. The fix usually comes back to the same misunderstanding: ACLs do not AND, they OR within a tier and AND across tiers. Every drift story I have ever investigated starts here.

The model in one paragraph

For a given operation on a record, ServiceNow evaluates ACLs at three tiers — table, field, and table.field. Within a tier, any matching ACL granting access wins. Across tiers, all must grant. Add a permissive table-level ACL and you have just unlocked everything no field-level ACL explicitly forbids.

Where the OR kills you

A vendor app drops in this ACL on incident:

Table: incident
Operation: read
Roles: itil
Condition: <empty>
Script: answer = true;

Now any other read ACL on incident is irrelevant for ITIL users. The assigned_to=javascript:gs.getUserID() ACL you added last quarter? Bypassed.

Three rules to live by

  1. Never write answer = true unconditionally. If the script always returns true, you have built a permission bypass.
  2. Field ACLs cannot make a record visible. They can only further restrict. Stop trying to “hide a record” with a field ACL.
  3. Roles on an ACL are an OR. Putting itil plus admin means either; not both.

The audit query

Find every ACL where the script body trivially evaluates to true:

var gr = new GlideRecord('sys_security_acl');
gr.addQuery('script', 'CONTAINS', 'answer = true');
gr.addQuery('condition', '');
gr.query();

Every row is a candidate for a real condition.

Use the ACL Debugger before the auditor does

Impersonate a representative user from each business unit, hit the record, and turn on the ACL debug log. The output names the winning ACL — usually a global one no one remembers writing.

What to do this week

Run the audit query above and review the top 25 hits. Replace each answer = true with an explicit condition or delete the ACL. Re-impersonate. The right people lose access, and that is the point.

[object Object]
Share