MOKSHA-2026-0034: Coalesce Blocking via VDI.other_config leaf-coalesce

Advisory IDMOKSHA-2026-0034
Semantic IDDOC-5
Published2026-04-24
CVSS 3.16.8 Medium
CVSS 3.1 VectorAV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
CVSS 4.07.1 High
CVSS 4.0 VectorAV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:H/SC:N/SI:N/SA:H
XAPI ObjectVDI
XAPI Fieldother_config:leaf-coalesce
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 vm-admin in XAPI-based hypervisors (XenServer, XCP-ng) can permanently block VHD leaf coalesce operations on any VDI by setting VDI.other_config:leaf-coalesce to false. The SM garbage collector (cleanup.py) reads this key and skips leaf coalesce when the value is false. Snapshot chains grow unbounded, consuming storage until the SR reaches capacity or the VHD chain exceeds the maximum depth. The attack requires a single API call, produces no alert, and the effect persists indefinitely. The same mechanism allows setting gc=false or coalesce=false to disable all garbage collection on a VDI. The leaf-coalesce key has no per-key RBAC protection in datamodel.ml.

Vulnerability Description

VDI.other_config is a Map(String, String) field writable by vm-admin. The leaf-coalesce key is consumed by the SM garbage collector at cleanup.py:2149-2245 to decide whether to perform leaf coalesce operations on a VDI.

The code path:

  1. vm-admin calls VDI.add_to_other_config(vdi, "leaf-coalesce", "false")
  2. The SM garbage collector reads VDI.other_config during its periodic scan
  3. cleanup.py:516 reads DB_LEAFCLSC = "leaf-coalesce" and checks its value
  4. If the value is "false" (LEAFCLSC_DISABLED), the GC skips leaf coalesce for this VDI
  5. Snapshot chains accumulate without being coalesced

Additional GC-disabling keys in VDI.other_config:

All three keys are unprotected by map_keys_roles. The VDI.other_config field only protects folder and XenCenter.CustomFields.* at _R_VM_OP.

Root Causes

  1. Missing RBAC protection. VDI.other_config has no map_keys_roles entry for leaf-coalesce, gc, or coalesce. All are writable by vm-admin.

  2. Direct SM GC control from user-writable field. The garbage collector's behavior is controlled by keys in a user-writable map field with no intermediate validation layer.

  3. No monitoring or alerting. When coalesce is disabled, no alert or audit event is generated. The condition is invisible to administrators until storage exhaustion occurs.

  4. Persistent effect. The key persists in the XAPI database indefinitely. Coalesce blocking survives VM restarts, host reboots, and pool maintenance operations.

Affected Systems

Directly Affected

Indirectly Affected

Exploitation Scenarios

Scenario Impact Pre-conditions Status
Leaf coalesce blocking Snapshot chains grow unbounded until SR fills vm-admin, VDI with snapshots on LVHD SR Source-traced
Full GC disablement Orphan VDIs accumulate, consuming storage indefinitely vm-admin, LVHD SR with VDI lifecycle operations Source-traced
Silent storage exhaustion SR reaches capacity, all VMs on the SR experience I/O errors vm-admin, coalesce blocked on one or more VDIs Modeled
Chain depth exhaustion VHD chain exceeds maximum depth, VDI operations fail vm-admin, repeated snapshots with coalesce blocked Modeled

Detection

Remediation

Short-Term Mitigations

Long-Term Fix

Add map_keys_roles. Protect leaf-coalesce, gc, and coalesce in datamodel.ml at _R_POOL_ADMIN to prevent vm-admin from controlling garbage collection behavior.

Separate GC policy from user-writable fields. Storage GC configuration should not be stored in other_config. Move GC policy to a dedicated, restricted configuration mechanism.

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