Domain separation is a logical boundary, not an isolation boundary. Tenants share Java application servers, one database, a MID Server pool and an admin-account namespace, so anything that operates beneath the platform — a platform-level vulnerability, a compromised admin account, or an integration that runs outside domain context — crosses every domain at once. When a tenant's risk profile cannot tolerate that shared substrate, the answer is a separate instance, not tighter domain configuration.
Activation status: This article describes the limits of what domain separation can defend against — failure modes that depend on the underlying single-instance architecture. Behavioral claims about CVE blast radius and admin-context query rewriting are docs-anchored to ServiceNowDocs Australia (commit
3b27d9a5) and to the documented CVEs in domain-7-threat-modeling. PDI activation block does not affect this article materially because the failure modes are platform-level, not activation-state-level.
What This Is
Domain separation enforces a logical boundary between tenants inside a single ServiceNow instance. The boundary is implemented by query rewriting, ACL evaluation in domain context, and per-tenant business logic — all running on the same Java application servers, the same database, the same MID Server pool, the same admin account namespace. Anything that bypasses the platform — a platform-level CVE, an admin-account compromise, a MID Server compromise, a clone-with-data event — defeats the boundary in a single step [ref: markdown/platform-security/bp-segregate-secure.md @ 3b27d9a5].
The canonical doc lays out four mechanisms for segregating data, ordered by comprehensiveness [ref: markdown/platform-security/bp-segregate-secure.md @ 3b27d9a5]:
- Customizing the reference architecture — qualifiers and filters within a single domain
- Contextual security + Before-Query business rules — additional layers on top of ACLs
- Domain separation — query-level data restriction (the layer this DOM-* module covers)
- Separate instances — segregation at the database and application layer
The choice between (3) and (4) is the central architecture decision for MSPs and regulated multi-entity operators. Shared Substrate Cross-Tenant Compromise is the article that names the exact failure modes that justify (4) over (3).
What domain separation does NOT separate
Per the canonical concept doc [ref: markdown/platform-security/bp-what-is-domain-separation.md @ 3b27d9a5]:
- System properties (
glide.*) — global, single-source-of-truth - Table schema (
sys_dictionary,sys_db_object) — global - Java/JavaScript runtime — same JVM serving all tenants
- Database — single MariaDB cluster with all tenant rows in the same tables
- MID Server pool (default config) — same agents serving discovery / integration jobs across tenants
- Update sets — applied platform-wide
- Admin sessions —
adminrole bypasses domain-aware query rewriting - Plugin activation state — global toggle
- Encryption keys (Edge Encryption, Field Encryption) — single platform-managed keystore
When ServiceNow Research published "Cross tenant intelligence" [ref: markdown/platform-security/bp-dom-sep-how-it-works.md @ 3b27d9a5], the framing was a feature — automatic data/metadata/business-logic handling for tenants with access to additional tenant data. The same mechanism is the failure surface when access controls collapse: there is no architectural firewall, only logical scoping.
Why This Is Dangerous
Risk class: single-event total compromise
Every protection in Domain Separation Posture Assessment / Cross-Domain Visibility Leaks / Custom Tables Missing sys_domain / ACL Misconfigurations in Domain Context sits behind the assumption that the platform is intact and admin sessions are honest. When that assumption fails, all per-tenant configuration becomes irrelevant simultaneously. The blast radius is all tenants on the instance, immediately.
The historical incident base for ServiceNow proves this is not theoretical:
| CVE / Incident | Year | Mechanism | Cross-tenant impact |
|---|---|---|---|
| CVE-2024-4879 / -5217 / -5178 (Assetnote) | 2024 | Unauthenticated Jelly template injection → RCE → full-DB read (CVSS 9.3) | Single bug, every tenant on the instance exposed simultaneously. → Jelly Template Injection RCE Chain (CVE-2024-4879, CVE-2024-5178, CVE-2024-5217) |
| CVE-2025-3648 ("Count(er) Strike", Varonis) | 2025 | Aggregate API count inference via conditional ACL evaluation | Domain separation does not change ACL evaluation order; inference works the same way against domain-separated tables. → Empty Condition ACLs on Sensitive Tables |
| CVE-2025-12420 ("BodySnatcher", AppOmni) | 2025 | Virtual Agent API allows unauthenticated impersonation by email; bypasses MFA/SSO (CVSS 9.3) | An attacker who impersonates an admin gains admin-context queries that bypass domain rewriting. Total tenant compromise from a single bug. |
| November 2023 ACL emergency response (ServiceNow proactive maintenance) | 2023 | Empty-condition ACLs across customer base | Domain separation does not protect tables whose ACLs grant unconditional read; the OOB tenants suffered the same misconfiguration shape. |
For each CVE that allowed unauthenticated platform-level access, the existence of domain separation made no difference. This is the substrate problem.
Attack Scenario 1: Admin compromise via phishing
Precondition: A 12-tenant MSP runs domain-separated ServiceNow. An MSP platform engineer has the global admin role to manage instance-wide configuration (plugins, system properties, MID Servers).
Compromise: The engineer clicks a phishing link, enters credentials on a fake SSO page. The attacker now has the engineer's session token.
Blast radius: The attacker logs in as the engineer. With admin role, queries bypass domain rewriting [behavior unverified on PDI; documented as platform behaviour and consistent with the architectural design — admin must be able to manage cross-tenant config]. The attacker runs:
// Read every tenant's incident table — admin role bypasses domain-aware rewriting
var inc = new GlideRecord('incident');
inc.query();
while (inc.next()) { /* exfiltrate */ }
In one session, all 12 tenants' incident records exfiltrate. No domain-separation control fires. No cross-tenant boundary alerts. The blast radius is the entire instance.
Attack Scenario 2: MID Server compromise leaks integration credentials across tenants
Precondition: The MSP runs a single MID Server pool serving discovery + integration jobs for all 12 tenants. (This is the default configuration — operators have to opt into per-tenant MID clusters.)
Compromise: An attacker compromises the MID Server VM (host-level — phishing the sysadmin, exploiting an unpatched OS vulnerability). The MID Server holds integration credentials in its keystore for every job it runs.
Blast radius: The MID Server's credentials cover all 12 tenants. Tenant A's ServiceNow → AD integration credentials, Tenant B's cloud-platform credentials, Tenant C's SAP RFC credentials — all on the same compromised host. Domain separation inside ServiceNow doesn't interact with this — the MID Server is upstream of the platform.
This is the failure mode that Shared Substrate Cross-Tenant Compromise names but the docs only obliquely address. The reference architecture docs [ref: markdown/platform-security/bp-sp-reference-arch-ds.md @ 3b27d9a5] [ref: markdown/platform-security/bp-sp-reference-arch-dedicated.md @ 3b27d9a5] [ref: markdown/platform-security/bp-sp-reference-arch-hybrid.md @ 3b27d9a5] describe alternative deployment patterns, but the trade-off framing stays at the platform level. → Integration Credential and Sensitive Payload Exposure, ECC Queue Security & Message Manipulation
Attack Scenario 3: Clone-with-data leaks cross-tenant production data into sub-prod
Precondition: Operator clones production to a sub-prod instance for performance testing. Production has 12 tenants. Sub-prod is a single test environment.
Outcome: All 12 tenants' production data lands on sub-prod, which has weaker access controls (test ACLs, test users with broader roles, no Domain Separation Center auditing). Anyone with sub-prod access has cross-tenant production data. → Sub-Production Instance Cloning & Data Exposure Risks
The clone preserves domain separation structurally (the sys_domain field values are copied), but the operational controls are different. A tenant whose data was supposed to never leave production now has copies in test. Domain separation didn't fail; the substrate (the clone job) did the wrong thing.
Attack Scenario 4: Platform plugin activation affects all tenants simultaneously
Precondition: The MSP installs a new plugin (e.g., a recommendation engine) into the production instance. The plugin's activation runs as system, activating across all domains.
Outcome: Tenant A wanted the plugin. Tenants B–L did not. The plugin is now active for all 12 tenants because plugin activation is global [ref: markdown/platform-security/bp-what-is-domain-separation.md @ 3b27d9a5 — "You can't separate some global standards and properties, such as system properties and table schema, per tenant"]. Tenant B's contractual scope didn't include the recommendation engine; their data is now flowing through it. This is configuration drift, not security compromise — but it's a contractual failure that domain separation cannot prevent.
How to Detect
This article is largely about what cannot be detected from inside the platform. Domain separation has no instrumentation for "an admin session is doing cross-tenant queries" — admin queries are valid by definition. The detections here are perimeter / configuration audits that surface the substrate-level risks:
PLACEHOLDER — verify table/field names on dev377226 (Australia, un-activated PDI). Most checks are configuration audits that do not require domain separation activation.
/* DOM-004 Detection Script — Read-only, safe in production
* Shared-substrate cross-tenant compromise audit.
*
* This script audits the substrate-level controls that exist OUTSIDE
* domain-separation enforcement. It runs whether or not domain separation
* is active because the failure modes apply equally.
*/
(function() {
var findings = [];
// 1. Count of users with global admin role across all domains
// Each is a single-event total-compromise vector.
var admins = new GlideRecord('sys_user_has_role');
admins.addQuery('role.name', 'admin');
admins.addQuery('user.active', true);
admins.query();
findings.push({
check: 'global_admin_count',
count: admins.getRowCount(),
severity: admins.getRowCount() > 10 ? 'CRITICAL' : (admins.getRowCount() > 5 ? 'HIGH' : 'WARN'),
note: 'Each global admin can bypass domain-aware query rewriting. Total tenant compromise on session compromise. Aim for the smallest workable number.',
cross_ref: 'ACL-004'
});
// 2. MID Server pool topology — are MID Servers segmented per tenant?
// VERIFY on PDI: ecc_agent table schema; MID Server cluster definitions live in ecc_agent_cluster (verify).
var midServers = new GlideRecord('ecc_agent');
midServers.addQuery('status', 'Up');
midServers.query();
var midCount = midServers.getRowCount();
findings.push({
check: 'mid_server_count',
count: midCount,
severity: 'INFO',
note: 'If MID Servers are not segmented per tenant, a single MID compromise leaks integration credentials across all served tenants. Review ecc_agent_cluster definitions and per-tenant assignments.',
cross_ref: 'INTEG-001'
});
// 3. Cross-tenant credential aliases on connection records
// Connections that reference shared credential aliases break the per-tenant credential isolation assumption.
// VERIFY on PDI: discovery_credentials / sys_alias schema.
var creds = new GlideRecord('discovery_credentials');
creds.addQuery('active', true);
creds.query();
findings.push({
check: 'shared_credential_count',
count: creds.getRowCount(),
severity: 'INFO',
note: 'Audit each credential against per-tenant scope. Credentials used by multiple tenants are a cross-tenant compromise vector.',
cross_ref: 'INTEG-002'
});
// 4. Plugin activation drift detection
// List plugins active in the last 90 days. Plugin activations affect all tenants;
// each should be ticketed per-tenant if the plugin's scope spans tenant data.
// VERIFY on PDI: v_plugin schema.
var plugins = new GlideRecord('v_plugin');
plugins.addQuery('active', true);
plugins.addQuery('sys_updated_on', '>=', gs.beginningOfLast90Days());
plugins.orderByDesc('sys_updated_on');
plugins.query();
var recentPlugins = [];
while (plugins.next()) {
recentPlugins.push({
id: plugins.getValue('id'),
name: plugins.getValue('name'),
activated: plugins.getValue('sys_updated_on')
});
}
findings.push({
check: 'recent_plugin_activations_90d',
count: recentPlugins.length,
severity: recentPlugins.length > 5 ? 'WARN' : 'INFO',
note: 'Plugin activations are global. Each should have a per-tenant impact assessment. Confirm the activation ticket reviewed cross-tenant data flow.',
plugins: recentPlugins
});
// 5. Sub-prod instances ingest production data via clone — is the clone exclusion list configured?
// The clone-with-data risk is platform-level; the protection is the clone exclusion / data-preserver setup.
// VERIFY on PDI: sys_clone_data_preserver schema.
// Note: sys_clone_data_preserver is in the Zurich poison_pills list — verify pre-Australia migration status.
var preservers = new GlideRecord('sys_clone_data_preserver');
if (preservers.isValid && preservers.isValid()) {
preservers.query();
findings.push({
check: 'clone_data_preserver_count',
count: preservers.getRowCount(),
severity: preservers.getRowCount() === 0 ? 'WARN' : 'INFO',
note: 'Clone-with-data preservers protect specific tables from being overwritten in clones. Production-clone-to-sub-prod with no preservers risks tenant data leaking into less-controlled environments.',
cross_ref: 'DATA-005'
});
}
gs.print(JSON.stringify(findings, null, 2));
})();
What this detection does NOT cover
- Live admin compromise. No platform mechanism flags "this admin is exfiltrating cross-tenant data." Detection requires SIEM-side log analysis on
syslog_transactionand on outbound-network egress patterns from MID Servers. - Platform-level CVEs. A zero-day in the Jelly engine affects all tenants the moment it's reachable. Detection is patch monitoring, not in-platform audit.
- Phishing-driven SSO bypass. Out of scope of the platform; covered by SAML SSO Misconfiguration & Authentication Bypass / Multi-Factor Authentication Bypass & Session Token Attacks.
Remediation
1. Constrain global admin count
Per the canonical principle that the smallest workable number of admins minimizes blast radius:
- Use role-elevation patterns (admin elevation only when needed, time-bounded).
- Audit the
adminrole assignment list quarterly. - Maintain a 1:1 mapping between active admins and named individuals — no shared service accounts with
admin.
This is a generic ServiceNow security recommendation that becomes critical in domain-separated MSPs. → ACL Role Breadth & Overly Permissive Role Assignments
2. Segment MID Server pools per tenant or per trust boundary
Per the reference architecture options [ref: markdown/platform-security/bp-sp-reference-arch-ds.md @ 3b27d9a5] [ref: markdown/platform-security/bp-sp-reference-arch-hybrid.md @ 3b27d9a5]:
- For high-sensitivity tenants, dedicated MID Server clusters reduce blast radius.
- The hybrid reference architecture explicitly addresses this — domain-separated platform with per-tenant MID infrastructure.
- For tenants with regulatory boundaries (DORA Art.28 ICT third-party arrangements), evaluate whether a separate instance is required, not just a separate MID pool.
3. Configure clone-with-data exclusions
Before any production-to-sub-prod clone:
- Configure
sys_clone_data_preserverfor any table holding regulated tenant data that should not propagate to lower environments. - Configure clone scrubbing rules for PII fields (anonymisation on clone).
- Review the clone target's access control surface — sub-prod admins are usually a different team than prod admins; they should not have cross-tenant production data.
- → Sub-Production Instance Cloning & Data Exposure Risks for the full clone-security pattern.
4. Plugin activation gate
Treat every plugin activation as a cross-tenant change. Pre-activation checklist:
- Document which tenants will benefit from the plugin
- Confirm each tenant's contractual scope includes the new functionality
- Identify tenants who explicitly opted out — can the plugin be configured to skip them, or does activation force them in?
- Get tenant-level approval where applicable
- After activation, verify each tenant's UI / data flow matches expectations
5. Use the dedicated-instance decision tree to escalate
Per [ref: markdown/platform-security/bp-ded-instance-decision-tree.md @ 3b27d9a5], the canonical decision framework: when a tenant's regulatory scope, data sensitivity, or contractual isolation requirement exceeds what domain separation can provide, recommend separate instances. The Shared Substrate Cross-Tenant Compromise detection findings are the inputs — high admin count, shared MID, regulated tenants, plugin churn — into that decision.
Regulatory Impact
- NIS2 Art.21§2(d) — supply chain security: This article is the supply-chain risk decomposition for MSP-style ServiceNow operators. CVE blast radius across customers IS supply-chain risk.
- NIS2 Art.21§2(j) — access control and authentication: Admin compromise → §2(j) finding. Mitigation requires role-elevation discipline and SIEM coverage.
- NIS2 Art.21§3 — cybersecurity supply chain: For shared-services platforms, this article is the documentation auditors will ask for.
- DORA Art.9§2 / §4(c) — segregation of ICT systems: This is the article that justifies escalation from domain separation to separate instances for business-critical financial functions.
- DORA Art.28 — ICT third-party arrangements: Where domain separation is the segregation control between regulated entities, DORA expects evidence the segregation withstands the documented failure modes here. If it doesn't, DORA expects separate instances.
- ISO/IEC 27001:2022 A.5.31 — legal/contractual: Tenant contracts that promise "your data is never visible to other customers" are violated by every failure mode in this article unless the tenant is on a separate instance.
- ISO A.8.21 — security in development and support processes: Plugin activation drift, MID Server cluster topology, and clone-with-data exclusions all map to A.8.21.
- GDPR Art.32§1(b) — confidentiality and integrity: Each documented attack scenario is a §32 incident.
- GDPR Art.32§2 — appropriate measures: Domain separation may be insufficient as a §32(2) measure for high-sensitivity processing; this article is the analysis to support that conclusion.
Expert Notes
Why this article is CRITICAL severity
Domain Separation Posture Assessment / Cross-Domain Visibility Leaks / Custom Tables Missing sys_domain / ACL Misconfigurations in Domain Context are HIGH because their failure modes leak data inside the platform's own bounded blast radius. Shared Substrate Cross-Tenant Compromise is CRITICAL because its failure modes have no platform-bounded blast radius. A platform-level CVE or admin compromise breaks every tenant simultaneously, and the platform offers no detection or mitigation for the breach until forensics post-event.
When domain separation is the wrong answer
The four-layer hierarchy from [ref: markdown/platform-security/bp-segregate-secure.md @ 3b27d9a5] (reference architecture → contextual security → domain separation → separate instances) is presented as a comprehensiveness ladder. Shared Substrate Cross-Tenant Compromise is the article that names the threshold: when a tenant's risk profile crosses what level (3) can credibly defend, level (4) is required. Recommending domain separation for tenants with that risk profile is the operator's decision — and a documented bad one when those tenants get compromised through one of the named scenarios above.
The dedicated-instance decision tree [ref: markdown/platform-security/bp-ded-instance-decision-tree.md @ 3b27d9a5] is the formal framework. Shared Substrate Cross-Tenant Compromise is the operational restatement of why the tree exists.
What to tell auditors
When an auditor asks "how does domain separation protect tenant X from tenant Y?" the honest answer has two parts:
- Inside the platform under normal conditions: query rewriting, ACL evaluation in domain context, per-tenant business logic — listed in Domain Separation Posture Assessment / Cross-Domain Visibility Leaks / ACL Misconfigurations in Domain Context.
- Failure modes outside that envelope: documented in Shared Substrate Cross-Tenant Compromise. The mitigations are at the architecture level (separate instances for the highest-sensitivity tenants), at the operational level (admin discipline, MID segmentation, clone exclusions), and at the SIEM level (admin-session anomaly detection).
A tenant model document that lists "highest-sensitivity tenants on dedicated instance, lower-sensitivity tenants on shared domain-separated instance" is the artefact auditors will accept as the right answer to the segregation question.