The vulnerability is an XML injection that occurs in a two-step process. First, an attacker needs to be able to control the inputs to the DOMImplementation.createDocumentType function. This function is flawed because it does not validate the publicId, systemId, or internalSubset arguments, instead storing them as-is within the created DocumentType node. This sets the stage for the injection.
Second, the application must serialize the document containing this crafted DocumentType node using XMLSerializer.serializeToString. This function is the second part of the vulnerability. When serializing the DocumentType node, it takes the previously stored publicId, systemId, and internalSubset values and writes them directly into the output XML string without any sanitization or escaping.
This allows an attacker to break out of the intended DOCTYPE declaration structure and inject arbitrary XML elements into the document. For example, by providing ]> in the internalSubset, an attacker can close the DOCTYPE declaration prematurely and inject elements that will be parsed as part of the XML body.
The patch confirms this analysis by introducing validation checks within the serialization logic for DocumentType nodes, but makes it an opt-in feature (requireWellFormed: true) to avoid breaking changes. The core vulnerable behavior remains the default. Therefore, any code path that calls XMLSerializer.serializeToString on a DocumentType node whose properties could be controlled by an attacker is vulnerable if the new requireWellFormed option is not used.
The two key functions that would appear in a runtime profile during exploitation are DOMImplementation.createDocumentType to create the malicious node, and XMLSerializer.serializeToString to trigger the injection during serialization.