Security
You receive a production incident: users with the 'incident_manager' role report they cannot edit the…
The question
The Intent Behind This Question
This is a classic ACL access regression that requires methodical diagnosis because multiple factors could cause it: a new conflicting ACL was created, an existing ACL condition changed, role membership was altered, or a field-level ACL is now taking precedence over table-level access. The key is distinguishing between user configuration issues versus platform configuration issues versus script failures.
Diagnostic Approach
Step 1: Verify Role Assignment - Confirm the user actually has 'incident_manager' role and it hasn't been removed or suspended. Use impersonation to test directly.
Step 2: Check ACL Evaluation Order - ServiceNow evaluates from most specific to most generic. A field-level ACL on 'incident.assignment_group' will override a table-level 'incident.*' ACL. Check if a new field-level ACL was recently created that denies access.
Step 3: Examine ACL Conditions - Review all ACLs matching this operation. Remember the real rule: the user must pass BOTH the matching table-level (record) ACL AND the matching field-level ACL, but when several ACLs match at the same point, passing ANY ONE of them grants access (OR). So the regression means the user now fails every matching rule at some level — look for a changed condition or role list on the ACL they used to pass, or a new more-specific field ACL that displaced the wildcard they relied on. A condition referencing a field value (like 'state != closed') might now be evaluating differently due to data changes.
Step 4: Enable Security Debug - Use the Debug Security Rules module to see exact ACL evaluation flow and which rule is denying access.
The Solution
// Diagnostic Script - Run as admin to list matching ACLs
var query = new GlideRecord('sys_security_acl');
query.addQuery('name', 'incident.assignment_group');
query.addQuery('operation', 'write');
query.query();
gs.info('=== ACLs on incident.assignment_group (write) ===');
while (query.next()) {
gs.info('ACL: ' + query.name + ' | Active: ' + query.active +
' | Condition: ' + query.condition);
// Roles are attached via the sys_security_acl_role m2m table,
// NOT a field on sys_security_acl:
var aclRole = new GlideRecord('sys_security_acl_role');
aclRole.addQuery('sys_security_acl', query.sys_id);
aclRole.query();
while (aclRole.next()) {
gs.info(' requires role: ' + aclRole.sys_user_role.getDisplayValue());
}
}
// FIX: repair or create the ACL in the UI (elevate to security_admin),
// attach the incident_manager role on the ACL form, and retest by
// impersonating an affected user. Do NOT script-insert ACLs in
// production — an unconditioned, unreviewed ACL is itself a security
// incident waiting to happen.Senior Considerations
- ACL Precedence Rules - Field-level ACLs take priority over table-level ACLs. If a field-level ACL denies access, even a permissive table-level ACL cannot override it. Check both levels.
- Condition Evaluation Failure - If an ACL script condition throws an error or references a missing field, access is denied by default. Always wrap conditions in try-catch and log failures.
- Contained Roles Count - ACLs are satisfied by contained (inherited) roles: a user whose role contains 'incident_manager' passes an ACL requiring 'incident_manager'. If access regressed, check whether a role-containment or group-role assignment changed rather than assuming direct assignment is required.
- Wildcard ACL Risks - The 'incident.*' wildcard grants access to all fields without specific ACLs. If a new field-level ACL was added last week, it now blocks that specific field even if the wildcard exists.
- Production Debugging Without Downtime - Use impersonation to test as the affected user rather than enabling debug mode globally. Use gs.info() logs sparingly in production ACL scripts to avoid performance impact.
- Avoid Quick Fixes - Don't simply delete the blocking ACL without understanding why it exists. It may have been added for security compliance. Document the root cause and coordinate with security team before removal.
- Test with Non-Admin Users - Admin users bypass ACLs by default. Always test ACL changes with actual non-admin users in a staging environment first.