- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
an hour ago - edited an hour ago
Real World Example: Number and Work Notes Fields Not Visible for Non-Admin Users on Tables Extending Task
Applies To: Any table extending the Task table | Platform Security | ACLs
Tested On: Zurich
I searched the community before writing this. There are posts about work notes visibility and ACL inheritance as separate topics, but nothing that walks through the full diagnosis end-to-end — the combination of admin_overrides, missing field-level read ACLs, and parent table inheritance all contributing to the same symptom. This article fills that gap. It is not a duplicate.
Situation
A non-admin user could not see the Number field or the Work Notes field on records from a custom table that extends the Task table. The user had the correct role and could open records — those two fields were simply missing. Admins could see everything normally.
Task
Three questions needed answering:
- Why are Number and Work Notes not visible to non-admin users?
- What ACL configuration is causing it?
- How do you fix it without breaking anything else?
Action
Step 1 — Audit all ACLs on your table (read-only script)
Before changing anything, inspect every ACL on your table. This script only reads — it makes no changes. Run it from System Definition → Scripts - Background:
// READ ONLY — Safe ACL Inspector
// No changes made
var tableName = 'your_table_name'; // <-- replace with your table
var gr = new GlideRecord('sys_security_acl');
gr.addQuery('name', 'STARTSWITH', tableName);
gr.orderBy('name');
gr.query();
gs.info('========== ACLs on: ' + tableName + ' ==========');
while (gr.next()) {
gs.info(
'[ACL] ' + gr.getValue('name') +
' | Op: ' + gr.getValue('operation') +
' | Active: ' + gr.getValue('active') +
' | Admin overrides: '+ gr.getValue('admin_overrides') +
' | Roles: ' + (gr.getValue('roles') || 'NONE') +
' | Created by: ' + gr.getValue('sys_created_by') +
' | sys_id: ' + gr.getValue('sys_id')
);
}
gs.info('========== Done — no changes made ==========');
Step 2 — Check parent table ACLs for the specific fields (read-only script)
Because your table extends Task, ACL rules on parent tables also apply. This script checks the inheritance chain for the fields that were missing:
// READ ONLY — Parent table ACL check
// No changes made
var tables = ['task', 'your_parent_table', 'your_table_name']; // <-- update
var fields = ['number', 'work_notes', 'comments_and_work_notes'];
for (var t = 0; t < tables.length; t++) {
for (var f = 0; f < fields.length; f++) {
var tbl = tables[t];
var field = fields[f];
var gr = new GlideRecord('sys_security_acl');
gr.addQuery('name', tbl + '.' + field);
gr.addQuery('active', true);
gr.query();
var found = false;
while (gr.next()) {
found = true;
gs.info(
'[FOUND] ' + tbl + '.' + field +
' | Op: ' + gr.getValue('operation') +
' | Admin overrides: '+ gr.getValue('admin_overrides') +
' | Roles: ' + (gr.getValue('roles') || 'NONE')+
' | sys_id: ' + gr.getValue('sys_id')
);
}
if (!found) {
gs.info('[MISSING] No active ACL: ' + tbl + '.' + field);
}
}
}
gs.info('========== Done — no changes made ==========');
Step 3 — Understand what the output reveals
The scripts revealed this pattern:
[ACL] your_table | Op: read | Admin overrides: 1 | Roles: NONE [MISSING] No active ACL: your_table.number [MISSING] No active ACL: your_table.work_notes [FOUND] task.work_notes | Op: read | Admin overrides: 1 | Roles: NONE
To understand why this causes the problem, two ServiceNow ACL concepts are important.
What admin_overrides = true means
Per ServiceNow KB0685046: when Admin overrides is checked on an ACL, users with the admin role automatically pass that ACL's permissions check — regardless of any role, condition, or script defined on it. Non-admin users must still satisfy all requirements normally.
Two exceptions worth knowing:
- The
nobodyrole takes precedence — an ACL assigned thenobodyrole blocks even admins, regardless of the admin_overrides setting. - The system property
glide.security.admin.override.accesstermcontrols this behaviour. Its default istrue. If it has been changed tofalsein your instance, admin_overrides may not work as expected.
How ServiceNow finds a matching field ACL
Per ServiceNow product documentation, ACL evaluation uses two gates. A user must pass Gate 1 before Gate 2 is checked. Within each gate, ServiceNow searches from most specific to most generic. The first ACL that evaluates to GRANT stops the search. If no ACL grants access, the field is denied.
Note on Xanadu and later releases: The Xanadu release introduced a new ACL decision type called Deny-Unless. Deny-Unless ACLs are always evaluated before Allow-If ACLs. If a user fails a Deny-Unless check, access is denied immediately. All existing ACLs prior to Xanadu were automatically converted to Allow-If type. The scenario described in this article involves standard Allow-If ACLs — the OOB type you will see on most instances.
Gate 1 — Table-level read ACL: Checks in order: your_table → task (parent) → * (wildcard) Non-admins pass because the table read ACL has no role restriction. Admins pass automatically via admin_overrides. Both proceed to Gate 2. Gate 2 — Field-level read ACL for 'number': 1. your_table.number <-- MISSING, continue 2. task.number <-- only WRITE ACLs exist here, no read, continue 3. *.number <-- nothing, continue 4. your_table.* <-- nothing, continue 5. task.* <-- nothing, continue 6. *.* <-- nothing, continue Result: no ACL granted access → field is DENIED for non-admins
The same Gate 2 search happens for work_notes. Even though task.work_notes read ACL exists, whether non-admins pass it depends on what roles it requires in your specific instance. Always check this using Script 2 above.
Step 4 — The fix
Create field-level read ACLs for number and work_notes directly on your table. This gives Gate 2 a matching ACL to GRANT access at step 1 of the search, before reaching any restrictive parent ACL.
Before you start: Creating ACLs requires the security_admin role. Elevate it first: profile picture dropdown → Elevate Roles → check security_admin.
Navigate to: System Security → Access Control (ACL) → New
Create ACL 1 — Number field read:
Type : record Operation : read Name — Table : your_table_name Name — Field : number Active : checked Admin overrides : checked Requires role : your_role_name Description : Allow [role] to read the number field on [table_name]
Create ACL 2 — Work Notes field read:
Type : record Operation : read Name — Table : your_table_name Name — Field : work_notes Active : checked Admin overrides : checked Requires role : your_role_name Description : Allow [role] to read the work_notes field on [table_name]
Role guidance: Use the role your non-admin users already have. Match the role pattern used by other field-level ACLs on the same table. Do not leave it blank unless you want all authenticated users to be able to read the field.
Result
After creating both field-level read ACLs, non-admin users with the correct role could immediately see both fields. No cache clear or re-login was needed.
Field | Root cause | Why fix works
------------|-----------------------------------------------|----------------------------
number | No field-level read ACL in the entire chain | New ACL matches at step 1
| → Gate 2 found nothing → field DENIED | of Gate 2 → GRANT → done ✅
------------|-----------------------------------------------|----------------------------
work_notes | No field-level read ACL on your table → | New ACL matches at step 1
| fell back to task.work_notes which may | of Gate 2 → GRANT → done ✅
| require a role non-admins do not have |
Key Takeaways
- Admin overrides = true means the admin role automatically passes that ACL — per KB0685046, this permits admins to pass the permissions check regardless of roles, conditions, or scripts on the ACL. Non-admins must satisfy all requirements normally. Exception: the
nobodyrole overrides this completely. Also be aware of the system propertyglide.security.admin.override.accessterm— if it has been changed from its default oftrue, admin_overrides behaviour will differ from what most developers expect. - When no field-level ACL grants access, the field is denied — ServiceNow searches the full inheritance chain from most specific to most generic. If nothing grants access, the field is denied. No error appears — the field simply disappears or shows blank. The only ways to find out which ACL is responsible are Debug Security Rules or a diagnostic background script.
- Work Notes needs both a read ACL and a write ACL — work_notes entries are stored in the
sys_journal_fieldtable, not directly in your table. The read ACL controls whether past entries appear in the activity stream. The write ACL controls whether the input box is shown. Both are needed. A missing read ACL hides past entries. A missing write ACL hides the input box. - Parent table ACLs apply to all extending child tables — ACL rules on the Task table automatically apply to every table that extends it. The source of a field visibility problem may not be on your table at all. Always check parent table ACLs using Script 2.
- Never test ACL changes as admin — always impersonate — admins automatically pass ACLs that have admin_overrides checked, giving a false positive. Impersonate a non-admin user with the relevant role. Then enable Debug Security Rules (System Security → Debugging → Debug Security Rules) and open the record — a debug icon appears next to each field showing exactly which ACL passed or failed.
Diagnostic Checklist
When a field is missing for non-admin users on a table extending Task:
[ ] Elevate to security_admin before working with ACLs
Profile dropdown → Elevate Roles → check security_admin
[ ] Confirm the field is on the form layout
Right-click form header → Configure → Form Layout
[ ] Check for a field-level READ ACL on your_table.fieldname
System Security → Access Control → filter Name = your_table.fieldname, Op = read
[ ] Check Script 2 output for parent table field ACLs
Look at what roles task.fieldname read requires in your instance
[ ] Confirm the affected user has the role the ACL requires
User record → Roles tab
[ ] Verify system property glide.security.admin.override.accessterm = true
System Properties → search the property name
Default is true — if false, admin_overrides may behave unexpectedly
[ ] Check for a UI Policy hiding the field
System UI → UI Policies → filter by your table
[ ] Check for a Data Policy affecting the field
System Policy → Data Policies → filter by your table
[ ] Check Dictionary for read_only = true
System Definition → Dictionary → search your table + field name
If true → create a Dictionary Override on your table, set read_only = false
[ ] Test by impersonating a non-admin user with the correct role
Profile picture → Impersonate User
[ ] Enable Debug Security Rules while impersonating
System Security → Debugging → Debug Security Rules
Open the record — click the debug icon next to the field
to see exactly which ACL passed or failed
Related community posts
These posts address parts of this issue :
- Work_Notes field invisible on custom table extending Task
- Number not visible for non-admin users on table extending Task
- Is there a special ACL for Work Notes and Additional Comments?
- Table inherited from Task — inherited fields
- ACL Evaluation: Admin Overrides and a System Property — Allen Andreas
If this helped, please mark it as Helpful. If you ran into a variation not covered here, drop a comment — happy to help.
Selva Arun ~ Meena
