MOKSHA-2026-0045: Arbitrary Bond Property Injection via PIF.other_config bond-*

Advisory IDMOKSHA-2026-0045
Semantic IDPOC-1
Published2026-04-24
CVSS 3.16.5 Medium
CVSS 3.1 VectorAV:N/AC:L/PR:H/UI:N/S:U/C:N/I:H/A:H
CVSS 4.05.1 Medium
CVSS 4.0 VectorAV:N/AC:L/AT:N/PR:H/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N
XAPI ObjectPIF
XAPI Fieldother_config:bond-*
Entry Rolepool-operator
ResearcherJakob Wolffhechel, Moksha

Affected Products

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

Summary

A pool-operator in XAPI-based hypervisors (XenServer, XCP-ng) can inject arbitrary bond configuration properties into OVS or Linux bonding by writing keys with the bond- prefix to PIF.other_config. The nm.ml:216-227 function extracts any key with the bond- prefix, strips the prefix, and passes the remainder as a bond property name with zero validation on property names or values. This enables bond mode changes (e.g., active-backup to balance-slb), bond timer manipulation, and injection of completely invalid parameters causing OVS errors and network disruption.

Vulnerability Description

PIF.other_config is a Map(String, String) field writable by pool-operator with zero map_keys_roles entries. The bond-* key prefix is consumed by the bond creation logic in nm.ml.

The code path:

  1. pool-operator calls PIF.add_to_other_config(bond_master_pif, "bond-mode", "balance-tcp")
  2. On PIF plug or bring_pif_up, nm.create_bond at nm.ml:216-227 is invoked
  3. The function iterates over pif_other_config, filters keys starting with bond-:
    let overrides = List.filter_map (fun (k, v) ->
      if String.starts_with ~prefix:"bond-" k then Some (String.sub_to_end k 5, v)
      else None
    ) master_rc.API.pIF_other_config
    
  4. The prefix is stripped, and the remaining key/value pair is injected as a bond property override
  5. Default bond properties are replaced by the attacker-controlled values
  6. Values are passed to OVS (ovs-vsctl bond configuration) or Linux bonding with no validation

This allows injection of any string as a bond property name and any string as its value. There is no whitelist of valid bond properties and no validation of values.

Root Causes

  1. Missing RBAC protection. PIF.other_config has zero map_keys_roles entries. All keys, including the bond-* prefix pattern, are writable by pool-operator.

  2. Missing input validation. The nm.ml:216-227 bond override mechanism accepts any key after the bond- prefix as a bond property name. No whitelist of valid bond properties is enforced. No validation of values is performed.

  3. Prefix-based key consumption. The bond- prefix pattern creates an open-ended injection surface - the number of injectable properties is unbounded.

  4. PIF.other_config has highest merge precedence. In the other_config merge chain (nm.ml:112-120), PIF.other_config overrides both Network.other_config and Pool.other_config. A PIF-level bond property override cannot be counteracted at the pool or network level.

Affected Systems

Directly Affected

Indirectly Affected

Exploitation Scenarios

Scenario Impact Pre-conditions Status
Bond mode override Change bond mode from active-backup to balance-slb, disrupting traffic distribution pool-operator, bonded PIF Source-traced
Bond timer manipulation Modify miimon, downdelay, updelay - cause slow failover or false link-down events pool-operator, bonded PIF Source-traced
Invalid property injection Inject non-existent bond properties causing OVS errors and bridge instability pool-operator, bonded PIF (OVS mode) Source-traced
BOC-1 chain vm-admin uses BOC-1 S3 to self-grant pool-operator, then injects bond properties vm-admin, BOC-1, bonded PIF Source-traced

Chaining Analysis

Detection

Remediation

Short-Term Mitigations

Long-Term Fix

Whitelist bond properties. Replace the open-ended bond- prefix extraction with a fixed whitelist of known valid bond properties (mode, miimon, updelay, downdelay, lacp-time).

Validate bond property values. For each whitelisted property, validate the value against the acceptable range (e.g., mode must be one of the known bond modes).

Add map_keys_roles. Protect bond-* keys at _R_POOL_ADMIN in datamodel.ml.

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