MOKSHA-2026-0067: Cross-Pool Metadata Injection via VDI.xenstore_data on Pool Join

Advisory IDMOKSHA-2026-0067
Semantic IDVXD-4
Published2026-04-24
CVSS 3.15.3 Medium
CVSS 3.1 VectorAV:N/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:N
CVSS 4.05.3 Medium
CVSS 4.0 VectorAV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N
XAPI ObjectVDI
XAPI Fieldxenstore_data
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 poison VDI.xenstore_data on a source pool, and the poisoned metadata crosses into a target pool when the source host joins the target pool or when VDIs are migrated cross-pool. The pool join code at xapi_pool.ml:1215 copies VDI records including xenstore_data without re-validation. This enables a compromised vm-admin on one pool to inject attacker-controlled storage metadata into a separate, previously uncompromised pool. The field has zero map_keys_roles restrictions, zero write-time validation, and zero cross-pool sanitization.

Vulnerability Description

XAPI pool join operations merge the database of the joining host into the pool master's database. VDI records are copied as part of this process.

The code path at xapi_pool.ml:1215:

~xenstore_data:vdi.API.vDI_xenstore_data

This line copies the joining host's VDI.xenstore_data directly into the target pool's VDI record. No validation, no sanitization, no re-generation from the SM driver.

The attack sequence:

  1. vm-admin poisons VDI.xenstore_data on source pool VDI with attacker-controlled values
  2. Source host initiates pool join to target pool
  3. xapi_pool.ml:1215 copies VDI records including poisoned xenstore_data to target
  4. Target pool now contains VDI records with attacker-controlled metadata
  5. Downstream consumers on the target pool trust the inherited metadata

Cross-pool migration (SXM - Storage XenMotion) follows a similar pattern: VDI records are recreated on the target pool using metadata from the source, including xenstore_data.

This vector requires pool join or cross-pool migration as a trigger event, making it less immediately exploitable than direct database writes. However, pool joins are a routine operational event in infrastructure lifecycle management (capacity expansion, host replacement, pool consolidation).

Root Causes

  1. No cross-pool sanitization. Pool join copies VDI metadata across pool trust boundaries without any validation or re-generation.

  2. Implicit trust of source pool data. The target pool assumes all metadata from the joining host is legitimate. There is no integrity verification.

  3. Missing RBAC protection. The source pool's vm-admin can poison metadata that will be trusted by the target pool.

  4. No write-time validation. The initial poisoning is possible because the field accepts any key-value pair without validation.

Affected Systems

Directly Affected

Indirectly Affected

Exploitation Scenarios

Scenario Impact Pre-conditions Status
Pool join contamination Target pool receives VDIs with poisoned xenstore_data vm-admin on source, pool join event Source-traced
Cross-pool migration contamination Migrated VDI carries poisoned metadata to target vm-admin on source, SXM migration Source-traced
Trust boundary violation Attacker on one pool injects data into another pool's database vm-admin on source, pool merge Source-traced
Persistent contamination Poisoned data persists on target pool after source host is removed vm-admin on source, pool join then eject Source-traced

Chaining Analysis

Detection

Remediation

Short-Term Mitigations

Long-Term Fix

Re-generate xenstore_data on pool join. Instead of copying the source pool's database field, query the SM driver on the target pool for fresh metadata after the VDI's storage is available.

Add cross-pool validation. Validate xenstore_data entries against a whitelist of SM-known keys during pool join. Reject or strip unknown keys.

Restrict write access. Change the field write role to _R_POOL_ADMIN to prevent vm-admin from poisoning the source data in the first place.

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