acl-security

ACL Security Patterns for ServiceNow

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "acl-security" with this command: npx skills add groeimetai/snow-flow/groeimetai-snow-flow-acl-security

ACL Security Patterns for ServiceNow

Access Control Lists (ACLs) are the foundation of ServiceNow security. They control who can read, write, create, and delete records.

ACL Evaluation Order

ACLs are evaluated in this order (first match wins):

  • Table.field - Most specific (e.g., incident.assignment_group )

  • *Table.` - Table-level field wildcard

  • Table - Table-level record ACL

  • Parent table ACLs - If table extends another

  • Global wildcard (catch-all)

ACL Types

Type Controls Example

record Row-level access Can user see this incident?

field Field-level access Can user see assignment_group?

client_callable_script_include Script Include access Can user call this API?

ui_page UI Page access Can user view this page?

rest_endpoint REST API access Can user call this endpoint?

Creating ACLs via MCP

// Table-level READ ACL snow_create_acl({ name: "incident", operation: "read", admin_overrides: true, active: true, roles: ["itil", "incident_manager"], condition: "current.active == true", script: "", })

// Field-level WRITE ACL snow_create_acl({ name: "incident.priority", operation: "write", roles: ["incident_manager"], condition: "", script: "answer = current.state < 6;", // Only if not resolved })

Common ACL Patterns

Pattern 1: Role-Based Access

// Condition: (empty - role check only) // Roles: itil, incident_manager // Script: (empty)

// Users with itil OR incident_manager role can access

Pattern 2: Ownership-Based Access

// Condition: current.caller_id == gs.getUserID() || current.assigned_to == gs.getUserID() || current.opened_by == gs.getUserID()

// User can access their own records

Pattern 3: Group-Based Access

// Script: ;(function () { var userGroups = gs.getUser().getMyGroups() answer = userGroups.indexOf(current.assignment_group.toString()) >= 0 })()

// User can access records assigned to their groups

Pattern 4: Manager Chain Access

// Script: ;(function () { var callerManager = current.caller_id.manager var currentUser = gs.getUserID()

// Check if current user is in caller's management chain while (callerManager && !callerManager.nil()) { if (callerManager.toString() == currentUser) { answer = true return } callerManager = callerManager.manager } answer = false })()

Pattern 5: Time-Based Access

// Script: ;(function () { var now = new GlideDateTime() var hour = parseInt(now.getLocalTime().getHourOfDayLocalTime())

// Only allow access during business hours (8 AM - 6 PM) answer = hour >= 8 && hour < 18 })()

Pattern 6: Data Classification

// Script: ;(function () { var classification = current.u_data_classification.toString() var userClearance = gs.getUser().getRecord().getValue("u_security_clearance")

var levels = { public: 0, internal: 1, confidential: 2, secret: 3 } answer = levels[userClearance] >= levels[classification] })()

Field-Level Security Patterns

Hide Sensitive Fields

// ACL: incident.u_ssn (Social Security Number) // Operation: read // Script: answer = gs.hasRole("hr_admin")

// Only HR admins can see SSN field

Read-Only After State Change

// ACL: incident.short_description // Operation: write // Script: answer = current.state < 6 // Can't edit after Resolved

// Prevent editing after resolution

Conditional Field Visibility

// ACL: incident.u_internal_notes // Operation: read // Condition: gs.hasRole("itil") || current.caller_id == gs.getUserID()

// ITIL users see all, callers see their own

Security Best Practices

  1. Principle of Least Privilege

// ❌ BAD - Too permissive // Roles: (empty) - allows everyone

// ✅ GOOD - Explicit roles // Roles: itil, incident_manager

  1. Deny by Default

// Create a catch-all deny ACL at lowest priority // Name: * // Operation: read // Condition: false // This ensures anything not explicitly allowed is denied

  1. Avoid Complex Scripts

// ❌ BAD - Complex script ACL (slow) ;(function () { var gr = new GlideRecord("sys_user_grmember") gr.addQuery("user", gs.getUserID()) gr.query() while (gr.next()) { // Complex logic... } })()

// ✅ GOOD - Use conditions when possible // Condition: gs.getUser().isMemberOf(current.assignment_group)

  1. Test ACLs Thoroughly

// Use "Impersonate User" to test ACLs as different users // Check: Navigation, List views, Forms, Related lists // Verify: Fields hidden, buttons disabled, records filtered

Debug ACLs

Enable ACL Debugging

// In a background script or temporarily in your code: gs.setProperty("glide.security.debug", "true") gs.log("ACL Debug enabled")

// Check System Logs for ACL evaluation details

Check User Permissions

// Check if current user can read a record var gr = new GlideRecord("incident") gr.get("sys_id_here")

gs.info("Can Read: " + gr.canRead()) gs.info("Can Write: " + gr.canWrite()) gs.info("Can Delete: " + gr.canDelete())

// Check field-level gs.info("Can read assignment_group: " + gr.assignment_group.canRead()) gs.info("Can write assignment_group: " + gr.assignment_group.canWrite())

Common Mistakes

Mistake Problem Solution

No ACLs on custom tables Anyone can access Create ACLs immediately

Only role-based ACLs No row-level security Add conditions for data segregation

Scripts that query DB Performance issues Use conditions or cache results

Testing only as admin Admin bypasses ACLs Test as actual end users

Forgetting REST APIs APIs bypass UI ACLs Create specific REST ACLs

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Security

instance-security

No summary provided by upstream source.

Repository SourceNeeds Review
Security

security-operations

No summary provided by upstream source.

Repository SourceNeeds Review
General

predictive-intelligence

No summary provided by upstream source.

Repository SourceNeeds Review