REST Anonymous Access Audit
This page describes the
nowisor-rest-anonymous-accesscheck from the nowisor Instance Scan Pack v1.0.0. The check audits a family of sevenglide.basicauth.required.*system properties that together gate authentication on the REST API, SOAP, WSDL, XSD, scripted REST processor, databroker REST processor, and UNL endpoint surfaces. The check emits a single finding that enumerates every property in the family and its current value, flagging any whose value is nottrue.
What this finding means
Your ServiceNow instance has at least one of the seven glide.basicauth.required.* properties set to a value other than true — or removed from sys_properties entirely. The finding's evidence object lists each property with its actual value so you can see which endpoint families currently accept unauthenticated requests.
The seven properties:
| Property | Endpoint family controlled |
|---|---|
glide.basicauth.required.api |
REST API (/api/now/table/*, the workhorse) |
glide.basicauth.required.scriptedprocessor |
Scripted REST APIs (/api/<namespace>/<name>) |
glide.basicauth.required.soap |
SOAP web services (/<table>.do?SOAP) |
glide.basicauth.required.wsdl |
WSDL endpoints |
glide.basicauth.required.xsd |
XSD endpoints |
glide.basicauth.required.databrokerrestapiprocessor |
Databroker REST processor |
glide.basicauth.required.unl |
UNL (Unified Navigation Loader) |
All seven default to true on Zurich Patch 6. When any of them is false, the corresponding endpoint family will respond to requests with no Authorization header — meaning any party with network access to the instance URL can call into the platform without credentials. The platform's ACLs still apply to what the unauthenticated caller can read or write, but the surface is now fundamentally different: the attacker doesn't need credentials to start probing.
Why it matters for your compliance
Anonymous API access is the most direct and most common data-exfil vector against ServiceNow. Every regulator that maps to ServiceNow audits this control.
NIS2 Article 21§2(d) — supply chain security including security-related aspects concerning the relationships between each entity and its direct suppliers. This article applies because anonymous endpoints are typically left open to support a legacy integration with a third-party supplier — and the supplier relationship becomes the lever the attacker uses to find and abuse the exposure. NIS2 expects the entity to enforce supply-chain hygiene, including denying the relationship-of-convenience that drives properties like these to false.
ISO 27001 A.5.16 — identity management. A.5.16 requires that identity management apply to all access paths. An unauthenticated REST endpoint has no identity attached to its callers — every request is anonymous, no audit trail, no accountability. This is structurally incompatible with the control.
DORA Article 9 — ICT risk management framework. DORA Article 9§4(c) covers detection of anomalous activities. An anonymous endpoint surfaces no anomalies at the identity layer because there is no identity to anomalize against; an attacker can paginate the entire sys_user table without ever logging a credential. This is a DORA finding in onsite reviews of financial entities.
Severity 1 (critical) reflects the binary failure mode: when any of these properties is false, the corresponding endpoint family is a discoverable, fully unauthenticated entry point. There is no useful compensating control short of upstream WAF rules — and WAF rules are not part of the platform's documented security boundary.
The attack path
The path is one of the most-published attack chains against ServiceNow, both because the impact is severe and because the technique is so cheap.
Step 1 — Discovery. An attacker identifies a ServiceNow instance URL via DNS records, email headers from automated notifications, public documentation, or simply by enumerating *.service-now.com subdomains. No credentials are required.
Step 2 — Probe. The attacker makes an unauthenticated REST call:
GET https://yourinstance.service-now.com/api/now/table/sys_user
?sysparm_limit=10
If glide.basicauth.required.api is true, the response is a 401 challenge. If it's false, the platform falls back to processing the request as the guest user and returns whatever the guest user is permitted to read.
Step 3 — Map the exposed surface. The attacker iterates through standard tables: sys_user, cmdb_ci_server, incident, change_request, kb_knowledge. Each table that returns a non-empty response is a fact about the guest user's effective ACLs — and many instances have over-permissive guest ACLs from years of accumulated changes.
Step 4 — Exfil. Once the attacker knows which tables are readable, they paginate through them using sysparm_offset. There is no rate limit on the unauthenticated path on most instances, so a determined attacker can pull the entire readable set in hours. The exfiltration leaves no fingerprint on the user authentication logs because there was no user authentication.
The same path applies to the other endpoint families: an attacker who can't reach the REST API tries SOAP, then WSDL, then the scripted REST processor, then UNL. Each family that returns data without authentication is an alternative vector.
How to fix it
Set every property in the family to true:
glide.basicauth.required.api = true
glide.basicauth.required.scriptedprocessor = true
glide.basicauth.required.soap = true
glide.basicauth.required.wsdl = true
glide.basicauth.required.xsd = true
glide.basicauth.required.databrokerrestapiprocessor = true
glide.basicauth.required.unl = true
Apply via System Properties for each entry. All seven default to true on Zurich Patch 6, so the typical fix is restoring the default rather than introducing a new constraint.
If an integration breaks after the change, the integration was authenticating as the guest user. The right fix is:
- OAuth 2.0 client credentials flow. For machine-to-machine integrations, this is the platform-recommended path. The integration registers an OAuth client, exchanges credentials for a token, and uses the token on every API call.
- Dedicated integration user with restricted role. If OAuth is not feasible, create a sys_user with a role scoped to the specific tables the integration needs. Never use an admin or
itiluser for integration access. - Scripted REST API with explicit authentication-not-required configuration. If you genuinely need a public endpoint (e.g., a public status page), build it as a Scripted REST API with
requires_auth = falseset explicitly on the operation, and tightly scope the endpoint's behavior. Do not disable the global property.
After the fix, audit the sys_user table for any user account whose authentication was being relied on for integrations and which might now fail. Rotate those credentials as part of the migration to OAuth.
How to verify the fix
Run this Background Script after applying the property changes:
/*
* Verify nowisor-rest-anonymous-access
* Read-only, safe for production.
* Confirms every glide.basicauth.required.* property is set to "true".
*/
(function verifyBasicAuthFamily() {
var SENTINEL = '__NOT_REGISTERED__';
var family = [
'glide.basicauth.required.api',
'glide.basicauth.required.scriptedprocessor',
'glide.basicauth.required.soap',
'glide.basicauth.required.wsdl',
'glide.basicauth.required.xsd',
'glide.basicauth.required.databrokerrestapiprocessor',
'glide.basicauth.required.unl'
];
var fails = 0;
for (var i = 0; i < family.length; i++) {
var value = gs.getProperty(family[i], SENTINEL);
if (value === SENTINEL) {
gs.print('[FAIL] ' + family[i] + ' is NOT REGISTERED.');
fails++;
} else if (value !== 'true') {
gs.print('[FAIL] ' + family[i] + ' = "' + value + '" (expected "true").');
fails++;
} else {
gs.print('[PASS] ' + family[i] + ' = true.');
}
}
gs.print('');
if (fails === 0) {
gs.print('All 7 properties enforced. Anonymous access blocked across the family.');
} else {
gs.print(fails + ' propert(y/ies) still allow anonymous access. Update via System Properties.');
}
})();
Re-run the nowisor scan after applying the fix. The check should no longer produce a finding.
What to do next
Anonymous API access is the entry point to most platform compromise paths. Closing it is necessary but not sufficient — the secondary controls matter once attackers must authenticate to reach the surface:
nowisor-mfa-enforcement— once an attacker has to authenticate, MFA is the next defense against credential-stuffing and phishing.nowisor-csrf-token-enforcement— authenticated requests still need CSRF protection; the property family above is about who can call at all, CSRF is about what authenticated callers can be tricked into doing.nowisor-external-auth-policy— when SSO is configured, ensure local login is disabled so attackers can't bypass IdP controls by authenticating directly to the platform.
Beyond the platform-level controls, the nowisor advisor product is being built to correlate anonymous-endpoint findings with the table-level ACL audit (which tables were specifically over-permissive to the guest user) so your remediation can focus on the tables that actually matter — not every table that ever had an ACL touched. Audit your REST surface with the advisor →