Access Control Rules (ACLs)
ACL Overview
Access Control Lists (ACLs) are ServiceNow's primary database-layer security mechanism. Every read, write, create, delete, or execute operation against platform data passes through ACL evaluation before being permitted or denied.
What ACLs Protect
ACLs are stored in the sys_security_acl table. Navigate to them via Security > Access Control (ACL) or type sys_security_acl.list in the filter navigator. Each ACL record defines one permission rule combining a target object, an operation, and a set of requirements the user must satisfy.
The Four Primary Operations
read
View record data, field values, or list results. Controlled separately from write — a user can have read-only access.
write
Modify an existing record or field value. Does not cover creating new records — that is governed by create.
create
Insert a new record into the table. Evaluated when a user submits a form for a new record or uses the API to POST.
delete
Remove an existing record from the table. Often locked down more tightly than write to prevent accidental data loss.
Additional Operations
| Operation | When It Applies | Typical Target |
|---|---|---|
execute |
Running a script, callable API endpoint, or service operation | Scripted REST APIs, workflow activities, processors |
report_on |
Using a field as a report filter, column, or grouping criterion | Fields that should not appear in reports for compliance reasons |
The Three Object Types
Record ACL
Controls access to an entire row within a table. If the record ACL denies access, the user cannot see the record at all — no fields are returned. Row-level security is implemented here using conditions and scripts.
Example: incident[READ] — who can read any incident row?
Field ACL
Controls access to a specific column within a table. Evaluated in addition to the record ACL — both must pass. Used to protect sensitive fields like salary, SSN, or medical information.
Example: incident.short_description[READ] — who can see this specific field?
Table ACL
Controls table-level operations such as schema access. Less commonly encountered on the exam than record and field types. Primarily governs schema-level operations.
Example: Table-level execute for scripted REST APIs.
ACL Anatomy — All Fields Explained
Every ACL record in sys_security_acl contains the following fields. Understanding each field's purpose is essential for both the exam and real-world ACL authoring.
| Field | Purpose | Notes / Example |
|---|---|---|
| Type | Defines the object scope: record, field, or table |
Most ACLs are type record or field |
| Operation | The access operation being controlled | read, write, create, delete, execute, report_on |
| Name | What is protected — format: table.field or table.* or table |
incident.caller_id, incident.*, *.* |
| Active | Checkbox — only active ACLs are evaluated | Deactivating an ACL disables it without deletion |
| Requires role(s) | Related list of roles; user must have at least one to pass the role check | itil, admin; empty list = any authenticated user |
| Condition | Filter expression evaluated against the current record; must evaluate to true |
assigned_to=javascript:gs.getUserID() |
| Script | Advanced server-side logic; must explicitly return true or return false |
return gs.hasRole('manager'); |
| Advanced | Checkbox that enables the Script field — must be checked to write ACL scripts | When unchecked, the script field is hidden and inactive |
| Admin overrides | When true (default), admin users bypass this ACL entirely | Set to false to enforce even for admins (sensitive data) |
| Description | Free-text explanation of the ACL's intent | Best practice: always fill in for maintainability |
ACL Name Patterns
The Name field determines what object the ACL protects. It follows a table.field convention with wildcards supported at both levels.
incident.short_description
Specific field on a specific table. Most targeted — highest specificity in evaluation.
incident.*
All fields on the incident table (and its extensions). Applies to every column not covered by a more-specific ACL.
incident
Record-level ACL for the incident table with no field qualifier. Controls access to entire rows.
task.*
Wildcard covering all fields on the task table and every table that extends task (incident, problem, change).
*.*
Global catch-all: applies to all fields on all tables. The fallback of last resort when no more-specific ACL matches.
task.* applies to incident, problem, change_request, and every other table that extends task. A more specific ACL on incident.* will override the inherited task.* ACL for incident records.
ACL Evaluation Order (CRITICAL — Most Tested)
ServiceNow evaluates ACLs from most-specific to least-specific. The moment a matching ACL is found, its result (allow or deny) is applied and evaluation stops. No further ACLs are checked.
Specificity Priority Order
| Priority | ACL Pattern | Description | Example |
|---|---|---|---|
| 1 — Highest | table.field with condition |
Exact table + exact field + record-level condition applied | incident.caller_id[READ] where assigned_to = user |
| 2 | table.field |
Specific table and specific field, no record condition | incident.caller_id[READ] |
| 3 | table.* |
All fields on a specific table | incident.*[READ] |
| 4 | *.field |
A specific field name on any table | *.sys_created_by[READ] |
| 5 — Lowest | *.* |
Global fallback — all fields on all tables | *.*[READ] |
Same-Specificity Rules: ALL Must Pass
When multiple ACLs exist at the same specificity level for the same table/field/operation combination, the user must pass all of them. There is no short-circuit allow at the same level — each ACL is an independent gate.
Example:
incident.caller_id[READ] denies access. The incident.*[READ] ACL that would allow access is never consulted because evaluation already concluded at the higher-specificity level.
The Three-Gate Check
Once the most-specific matching ACL is found, the user must pass all three internal checks. These run in sequence:
Role Check
Does the user have at least one of the roles listed on this ACL?
Empty role list = any authenticated user passes automatically
Condition Check
Does the optional filter condition evaluate to true for this record?
Evaluated after role check; no condition = automatic pass
Script Check
Does the optional ACL script return true?
Only runs if Advanced is checked; no script = automatic pass
Fail-Closed Behavior
Exception — Without High Security Plugin: On instances without the High Security plugin, the default behavior for missing ACLs may be more permissive. The High Security plugin enforces strict deny-by-default across the board. See Section 9 for details.
Admin Bypass
admin role bypass ACL evaluation entirely by default. The platform skips ACL checks for admin users, granting full access to all records and fields. This behavior can be overridden on individual ACL records by setting Admin overrides = false.
Role Matching Logic
The role check is the first gate in ACL evaluation. Understanding exactly how role matching works prevents common exam mistakes.
OR Logic Across Roles
When multiple roles are listed in an ACL's Requires role(s) list, the check uses OR logic — the user needs to have at least one of the listed roles. Possessing any single matching role is sufficient to pass the role check.
| ACL Roles Required | User's Roles | Role Check Result | Reason |
|---|---|---|---|
itil, manager |
itil |
PASS | User has itil — one match is enough |
itil, manager |
manager |
PASS | User has manager — one match is enough |
itil, manager |
itil, manager |
PASS | Has both; still passes (OR logic) |
itil, manager |
approver_user |
FAIL | Has neither required role |
| (empty) | any authenticated user | PASS | Empty list = no role requirement; all users pass |
Role Hierarchy and Inheritance
ServiceNow roles support a parent-child hierarchy. A parent role includes all permissions of its child roles. If an ACL requires role itil and a user has a role that contains itil as a child, the role check passes.
itil_manager contains itil as a child role, then a user with itil_manager automatically also has itil. Any ACL requiring itil will pass for that user even though they were not explicitly granted the itil role directly.
Empty Roles List — Important Behavior
The security_admin Role
Creating, editing, or deleting ACL records requires the security_admin role. This is a separate, elevated role that is not granted automatically with admin.
admin— Full platform administration, bypasses ACLs by default, cannot modify ACL records without security_adminsecurity_admin— Specifically grants the ability to create, modify, and delete ACL rules; does NOT automatically include admin platform permissions- An admin user who wants to edit ACLs must also be granted
security_adminseparately (or elevate to it) - This separation prevents admins from accidentally or maliciously tampering with security controls
Condition Evaluation
The Condition field on an ACL provides record-level (row-level) filtering. It is a standard ServiceNow filter expression that is evaluated against the current record being accessed.
How Conditions Work
- Conditions run after the role check — if the role check fails, the condition is never evaluated
- Both the role check AND the condition must pass for the ACL to allow access
- If no condition is specified, that check passes automatically
- The condition has access to the
currentobject (the record being evaluated) - JavaScript expressions can be embedded using the
javascript:prefix
Common Condition Patterns
// Show only records assigned to the current user
assigned_to=javascript:gs.getUserID()
// Show records belonging to any group the user is a member of
assignment_group=javascript:gs.getMyGroups()
// Records where caller is the current user
caller_id=javascript:gs.getUserID()
// Records where active flag is true
active=true
// Records in open state (1 = open in ITSM)
state=1
GlideSystem Methods Used in Conditions
| Method | Returns | Use Case |
|---|---|---|
gs.getUserID() |
sys_id of current user (String) | Match records where a reference field points to the current user |
gs.getUserName() |
Username (login name) String | Match string fields storing username values |
gs.getMyGroups() |
Comma-separated list of group sys_ids | Match records assigned to any of the user's groups |
gs.hasRole('rolename') |
Boolean true/false | Conditional access based on role membership within a condition expression |
gs.getUserID() returns the sys_id (not the username) of the currently logged-in user. It is the most commonly tested GlideSystem method in ACL context. Used in conditions to implement row-level security patterns like "users can only see their own records."
ACL Scripts
The Script field enables advanced, programmatic access control logic that goes beyond what filter conditions can express. ACL scripts run server-side and have full access to the ServiceNow scripting API.
Script Requirements
- The Advanced checkbox must be checked on the ACL to enable the Script field
- The script must explicitly
return trueto allow access orreturn falseto deny - Script runs after both the role check and the condition check
- If the script does not return anything, the behavior is undefined — always return explicitly
- The
currentobject provides access to the record being evaluated
Available Script Objects
| Object | Type | Description |
|---|---|---|
current |
GlideRecord | The record currently being evaluated for access. Access field values via current.field_name |
gs |
GlideSystem | Platform API: user identity, role checks, session info, logging |
gs.getUserID() |
String (sys_id) | Returns the sys_id of the currently logged-in user |
gs.hasRole('role') |
Boolean | Returns true if the current user has the specified role |
gs.hasRoleInGroup('role','group') |
Boolean | Returns true if user has the role within a specific group context |
ACL Script Examples
// Allow access only to manager or above
answer = gs.hasRole('itil_manager') || gs.hasRole('admin');
// Allow if current user is the caller or assigned agent
answer = (current.caller_id == gs.getUserID() ||
current.assigned_to == gs.getUserID());
// Allow if the record is in a specific state
answer = (current.state == 1 || current.state == 2);
// Check a related (referenced) record's field value
var grp = new GlideRecord('sys_user_group');
grp.get(current.assignment_group);
answer = (grp.manager == gs.getUserID());
// Combine role and field value check
if (gs.hasRole('itil')) {
answer = (current.priority == 1 || current.priority == 2);
} else {
answer = false;
}
- Use Condition for simple database-style filters (field = value, field IN list)
- Use Script for multi-step logic, boolean combinations, method calls, or when you need to query related records
- Scripts are more powerful but more expensive — conditions are evaluated with SQL-level efficiency, scripts require JavaScript execution
Record ACLs vs. Field ACLs
Understanding the relationship between record-level and field-level ACLs is one of the most commonly tested topics in the security section of the CSA exam.
Record ACLs
A record ACL controls whether a user can access the entire row. It is the outer gate — if the record ACL denies access, the user cannot see the record in any form: not in list views, not via form, not via API.
| Operation on Record ACL | Effect When Denied |
|---|---|
read |
Record is excluded from list results and form views; appears as if it does not exist |
write |
Record can be viewed but form fields are read-only; save operations are blocked |
create |
User cannot insert new records into the table; New/Insert operations fail |
delete |
Delete button is hidden; delete operations via API return a security error |
Field ACLs
A field ACL controls access to a specific column within a table. Field ACLs are evaluated in addition to the record ACL — both must pass for the user to interact with a specific field.
| Operation on Field ACL | Effect When Denied |
|---|---|
read |
Field is hidden on the form; field value is blank in list views; API returns empty string |
write |
Field is rendered read-only on the form; user can view the value but cannot edit it |
The Cumulative Rule
Failure Scenario: If a user passes the
incident[READ] record ACL but fails the incident.salary_band[READ] field ACL, they can see the incident record but the salary_band field will be blank/hidden.
Visual Flow: Record + Field ACL Evaluation
Table Wildcards and Fallback Behavior
Wildcard ACLs provide broad coverage when no specific rule exists. Understanding when wildcards are applied and which wildcards take precedence is essential for predicting ACL behavior.
Wildcard Reference
| Pattern | Applies To | Specificity | Common Use |
|---|---|---|---|
incident.short_description |
Exactly one field on one table | Highest (2) | Protect a single sensitive field |
incident.* |
All fields on the incident table | Medium (3) | Default field access policy for a table |
task.* |
All fields on task + all extending tables | Medium (3) | Single policy covering the full task hierarchy |
*.field_name |
A named field on any table that has it | Low (4) | Protect a field name globally (e.g., *.password) |
*.* |
Every field on every table | Lowest (5) — global fallback | Default platform-wide baseline access rule |
The *.* Global Catch-All
The *.* ACL is the fallback of last resort. When no more specific ACL matches for a given table/field/operation combination, ServiceNow falls through to the *.* ACL if one exists. If no *.* ACL exists either, the fail-closed rule applies and access is denied.
*.*[READ] ACL requiring a base authenticated user role, combined with specific ACLs on individual tables that grant access to particular user groups. This ensures baseline denial for unauthenticated access while allowing targeted grants.
Table Extension and Wildcard Inheritance
The task.* wildcard demonstrates an important behavior: because incident, problem, and change_request all extend task, an ACL on task.* automatically applies to all those extended tables unless a more specific ACL exists for the extended table.
task.*[READ] and incident.*[READ] exist, then for incident records, only incident.*[READ] is evaluated (higher specificity). The task.* ACL is not consulted for incidents when a more specific incident-level ACL exists.
High Security Plugin
The High Security Settings plugin (com.glide.security.high_security) enables strict security enforcement at the platform level. It is a critical topic for the CSA exam's security section.
What the Plugin Does
Strict ACL Enforcement
Enables fully enforced fail-closed ACL behavior: if no matching ACL exists for an operation, access is denied for all users — including admin.
Disables Admin Bypass
The default admin bypass of ACLs is disabled. Even users with the admin role must pass ACL checks like all other users. This is the most significant behavioral change.
security_admin Required
Creating, editing, or deleting ACL records strictly requires the security_admin role. This separation of duties prevents admins from modifying their own access rules.
Password Policies
Enforces configurable password strength rules: minimum length, complexity requirements (uppercase, digits, special characters), and password expiration intervals.
Session Controls
Adds configurable session timeout and idle session expiration to reduce risk from unattended authenticated sessions.
Account Lockout
Configures automatic account lockout after a specified number of consecutive failed login attempts to prevent brute-force attacks.
Standard vs. High Security Mode
| Behavior | Standard Mode | High Security Plugin |
|---|---|---|
| No matching ACL found | Access GRANTED (by default on many tables) | Access DENIED (strict fail-closed) |
| Admin bypass of ACLs | Enabled by default — admin skips ACL checks | Disabled — admin must pass ACLs like all users |
| Who can modify ACLs | admin or security_admin (depends on instance config) | security_admin only — strictly enforced |
| Password enforcement | Basic or none by default | Configurable strength, expiry, complexity rules |
| Session timeout | Platform default | Enforced, configurable per policy |
| Account lockout | Not enforced by default | Configurable lockout after N failed attempts |
| Recommended for | Development / sandbox instances | All production instances |
- Without High Security: no matching ACL = access GRANTED
- With High Security: no matching ACL = access DENIED
Key Exam Facts & Debugging
This section consolidates the highest-frequency exam facts for ACLs, including common trap questions and the debugging tools available on the platform.
Master Fact List
security_admin and admin are different roles. You need security_admin to create or edit ACL records. Having admin alone is not sufficient — these roles serve different purposes and are granted separately.
gs.hasRole('admin') returns true for users with the admin role. In standard mode, admin users bypass ACL evaluation entirely unless Admin overrides = false is set on the specific ACL. The High Security plugin removes the admin bypass globally.
Debugging ACL Issues
When a user reports unexpected access problems, ServiceNow provides built-in tools to diagnose ACL evaluation without requiring code changes.
Access Control Related List
Open any record and view the Access Controls related list (may need to be added via Personalize Related Lists). Shows which ACLs were evaluated for that record and their results.
Best for: quick field-level access debugging on a specific record
ACL Debug Logs
Enable debug logging via System Diagnostics > Session Debug > Security. The system log (syslog.list) will show detailed ACL evaluation including which ACLs were checked and why access was granted or denied.
Best for: deep-dive diagnosis when the source of denial is unclear
Security ACL Simulator
Navigate to Security > Diagnose > Access Control. Simulate the access path for a specific user against a specific record to see exactly which ACLs match and what their evaluation result is.
Best for: testing access configuration for a specific user scenario
sys_security_acl.list
Navigate directly to the ACL table via the filter navigator. Filter by table name, operation, and active status to find the specific ACLs governing the affected record or field.
Best for: reviewing all ACLs for a specific table
Quick Reference: ACL Decision Matrix
| Scenario | Standard Mode Result | High Security Result |
|---|---|---|
| No ACL exists for table/field/operation | GRANTED | DENIED |
| ACL exists, user has required role, no condition, no script | GRANTED | GRANTED |
| ACL exists, user does NOT have required role | DENIED | DENIED |
| ACL exists, role passes, condition fails | DENIED | DENIED |
| ACL exists, role passes, condition passes, script returns false | DENIED | DENIED |
| User has admin role, ACL admin overrides = true | GRANTED (bypasses ACL) | MUST PASS ACL |
| User has admin role, ACL admin overrides = false | MUST PASS ACL | MUST PASS ACL |
| Record ACL denied; field ACL would allow | DENIED (record gate blocked first) | DENIED |
- User navigates to a module → Role check: does the module appear in the navigator?
- User opens a record list → Record ACL [READ]: which rows are returned?
- Row-level condition on record ACL → Row filter: which specific records does this user see?
- User opens a record form → Field ACLs [READ]: which fields are visible/populated?
- User modifies a field → Field ACL [WRITE]: is this field editable?
- User saves the form → Record ACL [WRITE]: is this record updatable?
- User inserts a new record → Record ACL [CREATE]: can new records be created?
- User clicks delete → Record ACL [DELETE]: can this record be removed?