Cross-Scope Privilege Grants
This page describes the
nowisor-cross-scope-privilege-grantscheck from the nowisor Instance Scan Pack v1.0.0. The check queriessys_scope_privilegefor grants from non-global application scopes to the global scope with high-impact operations (write, create, delete) andstatus = 'allowed'. A single aggregate finding lists sample grants (capped at 20) showing the source scope, target type, target name, and operation; the evidence object includes a total count and overflow indicator.
What this finding means
Your instance has at least one sys_scope_privilege record granting a non-global scoped application the ability to write, create, or delete records in the global scope. Each such grant is a scope-escalation path — code running in the scoped application can perform privileged operations on data and configuration that the scope's documented boundary should not reach.
A few field-level details that matter for triage:
source_scope— the scoped application that holds the grant. This is the application whose code can perform the cross-scope operation. For example, "Admin Experience Framework" or "Now Assist Admin Console."target_scope— the scope being acted upon. For these findings, target_scope is alwaysglobal(the most-privileged scope on the platform).operation— the action permitted. The check filters towrite,create, anddeletebecause those are the mutation operations that affect platform state.readgrants are excluded from this finding (they're a different category of risk covered by general data-access auditing).status— must be'allowed'for the finding to fire. The platform also supports'denied'grants, but those are blocked at runtime and pose no escalation risk. The check filters specifically to allowed grants to focus on exploitable paths.target_name+target_type— the specific table, script include, or other artifact being granted access. The finding lists this so you can see which global-scope objects each application can mutate.
A note on the check's predicate history: the v1.0.0-build version of this check used invalid dot-walk syntax (source.scope and target.scope) that the ServiceNow query engine silently dropped. The result was that the check produced zero findings on a real instance — the predicate didn't filter, the underlying data had matches, but the loop never iterated. Tier 2 verification surfaced the issue, and the predicate was rewritten with the correct flat field names (source_scope and target_scope) plus the status='allowed' filter. The fix is documented in V1_RETROSPECTIVE_TIER2.md. From v1.0.0 GA forward, the check produces correct findings.
Why it matters for your compliance
Cross-scope privilege grants are how scoped applications interact with each other and with the global scope. The architecture exists for legitimate reasons — third-party apps need to integrate, custom apps need to interact with platform data. But the same mechanism is the lever for scope-escalation when grants are over-broad or granted to compromised apps.
NIS2 Article 21§2(a) — risk analysis and information system security policies. NIS2's risk-analysis expectations include the supply-chain and integration surfaces — every cross-scope grant is a documented decision about what one piece of code can do to another. The finding surfaces those decisions so they can be reviewed.
ISO 27001 A.8.3 — information access restriction. A.8.3 expects access restrictions to be aligned with the access control policy. Cross-scope grants are technical implementations of "this application can write to this global-scope target." When grants accumulate without periodic review, the implementation diverges from the documented policy.
The check is severity 2 (high) because the failure mode is conditional: the grant itself is not active exposure, but it pre-positions exposure for any future compromise of the scoped application. On a stable instance with 70-80 high-impact grants (typical for an instance with many third-party apps), each grant is a question worth answering — but the answer is often "yes, this is intentional and approved."
The attack path
The path runs through compromise of a scoped application.
Step 1 — Identify a scoped app with high-impact grants. The attacker enumerates sys_scope_privilege (typically requires admin-level access for the enumeration, but the grant data is also visible to anyone with read access on the table). They identify a candidate: a custom scoped application with write grants to global for several table types.
Step 2 — Compromise the scoped application. Multiple paths exist:
- Compromised developer account. A developer with write access to the scoped application's Script Includes can plant a malicious Business Rule or Script Include in the scope. When the platform invokes the code (because of a triggering event the developer can also schedule), the code executes with the scope's privileges — including the cross-scope grant.
- Update set replay. A historical update set can be applied to the current instance, restoring an older state of the scoped application's code that contains attacker-prepared malicious logic.
- Direct script modification. If the scoped application's Script Includes are editable by a broader audience than expected (an ACL gap), an attacker with
itil-level access may be able to modify the code directly.
Step 3 — Exercise the grant. The compromised application's code executes a GlideRecord operation against the global-scope target. The platform consults sys_scope_privilege, sees the allowed grant, and permits the operation. The mutation happens.
Step 4 — Operate. The mutation might be: granting an admin role to a target user, modifying an ACL to weaken access controls, deleting an audit record, or inserting a backdoor business rule that fires on future record creation. The action appears in sys_audit as performed by the scoped application — not by an individual user — which can obscure the attribution if the defender isn't watching the application activity specifically.
The defense is to audit the grants regularly. The application's developer team should be able to articulate, for every grant, the business case that justifies it. Grants without articulable cases are candidates for removal.
How to fix it
The remediation is a per-grant review.
Step 1 — Open the grant list. Use the URL pattern from the finding's evidence to filter sys_scope_privilege:
/sys_scope_privilege_list.do?sysparm_query=source_scope.scope!=global^target_scope.scope=global^operationINwrite,create,delete^status=allowed
This shows every high-impact grant the check is auditing.
Step 2 — Categorize each grant. For each row:
Vendor-provided integration grant — the grant ships with a third-party application from the ServiceNow store. Verify the vendor's documentation describes the grant; document the dependency in your application inventory.
Custom app's internal grant — the grant was created by your developers when building a custom scoped application. Confirm the business case: what global-scope operation does the custom app need to perform, and why couldn't it be done with a less privileged mechanism (e.g., a scheduled job running in global scope that the custom app triggers)?
Grant of unknown origin — the grant exists but no one knows why. This is the highest-priority category. Either find the documentation (in change records, deployment notes, or the developer's commit messages), or remove the grant and observe what breaks. A grant that nothing depends on is a grant that should not exist.
Historical grant from a deprecated app — the source application is no longer in use but its grants remain. Remove them. Scoped application uninstallation does not always cascade-clean its privilege grants.
Step 3 — Tighten the grants that remain. For each grant you retain, verify that:
- The operation is actually needed (some grants are over-broad —
writewhen onlyupdateon a specific table is needed). - The target is as narrow as the platform allows (grant to a specific table rather than a category of tables).
- The grant has a documented owner who renews the business case annually.
Step 4 — Establish review cadence. Set up a quarterly review (or annually for stable environments) where each grant is re-confirmed. The review record becomes the compliance documentation.
How to verify the fix
/*
* Verify nowisor-cross-scope-privilege-grants progress
* Read-only, safe for production.
* Counts high-impact cross-scope grants by source scope.
*/
(function auditGrants() {
var bySource = {};
var gr = new GlideRecord('sys_scope_privilege');
gr.addQuery('source_scope', '!=', 'global');
gr.addQuery('target_scope', 'global');
gr.addQuery('operation', 'IN', 'write,create,delete');
gr.addQuery('status', 'allowed');
gr.query();
while (gr.next()) {
var src = gr.getDisplayValue('source_scope') || gr.getValue('source_scope');
bySource[src] = (bySource[src] || 0) + 1;
}
var names = Object.keys(bySource).sort();
gs.print('=== High-impact cross-scope grants by source ===');
gs.print('Total source scopes: ' + names.length);
gs.print('');
var total = 0;
for (var i = 0; i < names.length; i++) {
gs.print(' ' + names[i] + ': ' + bySource[names[i]] + ' grant(s)');
total += bySource[names[i]];
}
gs.print('');
gs.print('Total high-impact grants: ' + total);
})();
Track the count over time. A successful remediation reduces the number of source scopes (apps that hold any grants) and the per-app grant count. The expected end state is "every remaining grant has a documented owner and an approved business case."
What to do next
Cross-scope grants interact with the broader privilege-cluster findings:
nowisor-oob-acl-modifications— baseline ACLs and cross-scope grants together determine effective access. A weakened ACL combined with a high-impact grant is the worst-case exposure.nowisor-admin-role-concentration— every admin can modifysys_scope_privilege. A wider admin population means more potential grant-modifiers.nowisor-domain-separation-script-include— on DS-active instances, scope grants and domain boundaries interact in complex ways.
For organizations with significant scoped-app deployments (custom apps, third-party integrations), the nowisor advisor product is being built to group cross-scope findings by the source application — surfacing which apps hold the highest aggregate privilege weight, so app inventory and security review align with the actual exposure surface. Audit your scope privilege surface →