MOKSHA-2026-0003: System Domain Privilege Escalation via is_system_domain

Advisory IDMOKSHA-2026-0003
Semantic IDVOC-1
Published2026-04-24
CVSS 3.19.9 Critical
CVSS 3.1 VectorAV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
CVSS 4.08.6 High
CVSS 4.0 VectorAV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:H/SC:H/SI:H/SA:H
XAPI ObjectVM
XAPI Fieldother_config:is_system_domain
Entry Rolevm-admin
ResearcherJakob Wolffhechel, Moksha

Affected Products

VendorProductVersions
Citrix / Cloud Software GroupXenServer / Citrix Hypervisorall versions (shared XAPI codebase)
VatesXCP-ng8.3.0

Summary

A user with the vm-admin role can promote any VM to system domain status by writing is_system_domain=true to VM.other_config. This key is intended as an internal infrastructure flag set only by XAPI itself, but VM.other_config has no map_keys_roles protection for this key. A system-domain VM bypasses VBD sharing constraints, gains access to the query_services operation, and bypasses lifecycle restrictions - capabilities reserved for XAPI infrastructure components. Combined with MOKSHA-2026-0008 (VOC-2 storage_driver_domain), the promoted VM triggers PBD detach operations on VM shutdown, enabling storage denial-of-service against arbitrary SRs.

Vulnerability Description

VM.other_config is a Map(String, String) field in the XAPI data model. The is_system_domain key controls whether a VM is treated as an infrastructure system domain. XAPI reads this key in system_domains.ml:30-35:

let is_system_domain snapshot =
  snapshot.API.vM_is_control_domain
  ||
  let oc = snapshot.API.vM_other_config in
  List.mem_assoc system_domain_key oc
  && bool_of_string (List.assoc system_domain_key oc)

The function checks is_control_domain (a read-only boolean) OR the other_config key. Since the other_config path has no RBAC protection, any vm-admin can set it to true on any VM.

The set_is_system_domain function at system_domains.ml:45-52 performs no validation - it directly writes to other_config and creates a system_domains entry in the database.

Impact of System Domain Status

A VM promoted to system domain status:

  1. Bypasses VBD sharing constraints. The VBD sharing check at xapi_vbd_helpers.ml exempts system domains, allowing concurrent write access to non-sharable VDIs. A regular VM mounting a VDI already in use by another VM is blocked; a system-domain VM is not.

  2. Gains access to query_services. The query_services VM operation (xapi_vm_lifecycle.ml:718-720) requires is_system_domain=true. This operation is gated specifically for infrastructure VMs.

  3. Bypasses lifecycle restrictions. System domains are exempted from certain lifecycle state machine checks, allowing operations that would be rejected on regular VMs.

Root Causes

  1. Missing per-key RBAC. VM.other_config protects only three keys via map_keys_roles: pci (pool-admin), folder (vm-op), and XenCenter.CustomFields.* (vm-op). The is_system_domain key has no per-key protection and is writable by vm-admin.

  2. Infrastructure key in user-writable map. System domain designation is stored in a user-writable map field rather than as a protected internal-only property. The intent was for this key to be set only by XAPI internal code paths, but the API does not enforce this.

  3. set_other_config RBAC bypass. Even if map_keys_roles were added for this key, the set_other_config method bypasses all per-key checks.

Affected Systems

Directly Affected

Indirectly Affected

Exploitation Scenarios

Scenario Impact Pre-conditions Status
VBD sharing bypass Concurrent write access to non-sharable VDIs owned by other VMs Target VDI must be on an accessible SR 6/6 PASS (live-tested)
query_services access Access to infrastructure-only VM operation None Confirmed (source trace + live test)
Lifecycle restriction bypass Operations rejected on regular VMs succeed on system domains None Confirmed (source trace)
VOC-1 + VOC-2 chain System domain status + storage_driver_domain = PBD detach DoS on VM shutdown Set both keys on same VM Write confirmed; PBD detach absorbed by state race in current versions
VOC-1 + BOC-1 chain System domain + root access = full infrastructure compromise BOC-1 provides root access Modeled (compound scenario)

Detection

Remediation

Short-Term Mitigations

Long-Term Fix

RBAC: Add map_keys_roles entry for is_system_domain requiring _R_LOCAL_ROOT_ONLY in datamodel_vm.ml. This key should not be writable by any API user.

Validation: The is_system_domain key should only be writable by XAPI internal code paths. Add a check in the write path to reject external API calls setting this key.

Architecture: Move system domain designation out of other_config into a protected internal-only field that cannot be set via the map API.

Upstream patches exist. They are held privately pending coordinated disclosure.

Disclosure

Disclosure:

References

Credits

Discovered and reported by Jakob Wolffhechel, Moksha.

Jakob Wolffhechel · Moksha · Copenhagen
jakob@wolffhechel.dk · +45 3170 7337
Published 2026-04-24 08:00 CEST · cna.moksha.dk · shittrix.moksha.dk