From c789406edfaa64c70512df5c9c4c00456c95cc75 Mon Sep 17 00:00:00 2001 From: catborise Date: Sat, 3 Oct 2026 17:56:47 +0300 Subject: [PATCH] fix(instances): add_network escapes posted values add_network built the interface XML with f-strings, so a posted model or nwfilter could add arbitrary devices to the domain. It is built with lxml now; a missing MAC is left to libvirt instead of address='None'. --- vrtManager/instance.py | 24 +++++++++++------------- vrtManager/test_change_network.py | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/vrtManager/instance.py b/vrtManager/instance.py index 14a446a2..a65ec69f 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -1709,23 +1709,21 @@ class wvmInstance(wvmConnect): else: interface_type = "direct" - # network modes not handled: default is bridge - - xml_iface = f""" - - """ + # Built with lxml so posted values are escaped, never parsed as XML. + iface = etree.Element("interface", type=interface_type) + if mac_address: # otherwise libvirt generates one + etree.SubElement(iface, "mac", address=mac_address) if interface_type == "network": - xml_iface += f"""""" + etree.SubElement(iface, "source", network=source) elif interface_type == "direct": - xml_iface += f"""""" - elif interface_type == "bridge": - xml_iface += f"""""" + etree.SubElement(iface, "source", dev=source, mode="bridge") else: - raise libvirtError(f"'{interface_type}' is an unexpected interface type.") - xml_iface += f"""""" + etree.SubElement(iface, "source", bridge=source) + if model: + etree.SubElement(iface, "model", type=model) if nwfilter: - xml_iface += f"""""" - xml_iface += """""" + etree.SubElement(iface, "filterref", filter=nwfilter) + xml_iface = etree.tostring(iface).decode() if self.get_status() == 1: self.instance.attachDeviceFlags(xml_iface, VIR_DOMAIN_AFFECT_LIVE) diff --git a/vrtManager/test_change_network.py b/vrtManager/test_change_network.py index 7da19837..8bc8b015 100644 --- a/vrtManager/test_change_network.py +++ b/vrtManager/test_change_network.py @@ -52,5 +52,28 @@ class TestChangeNetwork(unittest.TestCase): self.assertEqual(flags, VIR_DOMAIN_AFFECT_CONFIG) +class TestAddNetworkXml(unittest.TestCase): + def attached(self, **kwargs): + from lxml import etree + + inst = stopped_instance() + inst.add_network(**kwargs) + return etree.fromstring(inst.instance.attachDeviceFlags.call_args[0][0]) + + def test_posted_values_cannot_inject_elements(self): + iface = self.attached( + mac_address="52:54:00:00:00:05", + source="default", + model="virtio'/>", + ) + self.assertEqual([el.tag for el in iface], ["mac", "source", "model", "filterref"]) + self.assertEqual(iface.find("model").get("type"), "virtio'/>