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'/>