packages/opencode/src/bundled-skills/acl-security/SKILL.md
This skill should be used when the user asks to "create ACL", "access control", "security rule", "restrict access", "role based access", "row level security", "field level security", or any ServiceNow ACL and security configuration.
npx skillsauth add groeimetai/snow-flow acl-securityInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Access Control Lists (ACLs) are the foundation of ServiceNow security. They control who can read, write, create, and delete records.
ACLs are evaluated in this order (first match wins):
incident.assignment_group)* - Global wildcard (catch-all)| 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? |
// 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
})
// Condition: (empty - role check only)
// Roles: itil, incident_manager
// Script: (empty)
// Users with itil OR incident_manager role can access
// Condition:
current.caller_id == gs.getUserID() || current.assigned_to == gs.getUserID() || current.opened_by == gs.getUserID()
// User can access their own records
// Script:
;(function () {
var userGroups = gs.getUser().getMyGroups()
answer = userGroups.indexOf(current.assignment_group.toString()) >= 0
})()
// User can access records assigned to their groups
// 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
})()
// 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
})()
// 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]
})()
// ACL: incident.u_ssn (Social Security Number)
// Operation: read
// Script:
answer = gs.hasRole("hr_admin")
// Only HR admins can see SSN field
// ACL: incident.short_description
// Operation: write
// Script:
answer = current.state < 6 // Can't edit after Resolved
// Prevent editing after resolution
// ACL: incident.u_internal_notes
// Operation: read
// Condition:
gs.hasRole("itil") || current.caller_id == gs.getUserID()
// ITIL users see all, callers see their own
// ❌ BAD - Too permissive
// Roles: (empty) - allows everyone
// ✅ GOOD - Explicit roles
// Roles: itil, incident_manager
// Create a catch-all deny ACL at lowest priority
// Name: *
// Operation: read
// Condition: false
// This ensures anything not explicitly allowed is denied
// ❌ 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)
// Use "Impersonate User" to test ACLs as different users
// Check: Navigation, List views, Forms, Related lists
// Verify: Fields hidden, buttons disabled, records filtered
// 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 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())
| 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 |
development
This skill should be used when the user asks to "App Engine Studio", "workspace builder", "custom workspace", "AES", "low code", "app development", "studio", or any ServiceNow App Engine Studio development.
tools
This skill should be used when the user asks to "create a widget", "build a widget", "service portal widget", "sp_widget", "fix widget", "widget not working", "ng-click not working", or any Service Portal widget development.
development
This skill should be used when the user asks to "create chatbot", "virtual agent", "VA topic", "NLU", "conversation", "chat flow", "topic block", or any ServiceNow Virtual Agent development.
development
This skill should be used when the user asks to "vendor", "supplier", "contract", "procurement", "SLA", "vendor risk", "vendor performance", or any ServiceNow Vendor Management development.