CVE-2026-53723
Description
Guzzle Services prior to 1.5.4 fails to escape CDATA terminator in XML serialization, allowing injection of arbitrary XML elements into outgoing requests.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Guzzle Services prior to 1.5.4 fails to escape CDATA terminator in XML serialization, allowing injection of arbitrary XML elements into outgoing requests.
Vulnerability
In guzzlehttp/guzzle-services versions prior to 1.5.4, the XML request serializer uses XMLWriter::writeCData($value) to encode values containing <, >, or &. If an attacker-controlled input contains the CDATA terminator ]]>, the CDATA section closes prematurely and the remainder of the value is interpreted as raw XML markup. This affects applications that serialize outgoing requests with location: xml parameters where the value is serialized as XML element text (not an attribute) and the input is untrusted and not constrained by a safe enum, pattern, or custom filter that excludes ]]>. The downstream service must parse the generated XML structurally for the injection to have effect. [1][2][3]
Exploitation
An attacker needs to supply input containing ]]> in a parameter that is serialized as XML element text via location: xml. No special authentication is required if the application accepts untrusted input (e.g., user, tenant, or third-party data). The attacker does not need to control the service description or schema. The injected ]]> closes the CDATA section, and any subsequent characters become XML markup, allowing the attacker to insert arbitrary elements, attributes, or text nodes into the request body. [2][3]
Impact
Successful exploitation allows an attacker to inject arbitrary XML elements into the outgoing request body. Depending on the receiving service, this can alter operation semantics, smuggle privileged fields, bypass modeled parameter boundaries, or create conflicting duplicated elements. The vulnerability is an outgoing request-body integrity issue; it does not affect response parsing directly. However, second-order attacks are possible if attacker-controlled response XML is parsed and later used as a location: xml request parameter. [2][3]
Mitigation
The vulnerability is fixed in guzzlehttp/guzzle-services version 1.5.4. Users should upgrade to this version or later. As a workaround, ensure that any untrusted input used in location: xml parameters is constrained by a safe enum, pattern, or custom filter that excludes the ]]> sequence. Users who only use Guzzle Services to deserialize HTTP response bodies are not directly affected. [2][3]
- GitHub - guzzle/guzzle-services: Provides an implementation of the Guzzle Command library that uses Guzzle service descriptions to describe web services, serialize requests, and parse responses into easy to use model structures.
- CVE-2026-53723 - GitHub Advisory Database
- XML Injection via CDATA Terminator in guzzlehttp/guzzle-services XML Request Serialization
AI Insight generated on Jun 11, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1- Range: < 1.5.4
Patches
1d78052e3ccf1Prevent XML CDATA injection (#259)
3 files changed · +73 −1
CHANGELOG.md+4 −0 modified@@ -1,5 +1,9 @@ # CHANGELOG +## 1.5.4 - Upcoming + +* Prevent XML CDATA injection during request serialization (GHSA-q8r6-5hfw-5jff) + ## 1.5.3 - 2026-06-02 * Harden request serialization state after failures
src/RequestLocation/XmlLocation.php+16 −1 modified@@ -217,13 +217,28 @@ protected function writeElement(\XMLWriter $writer, $prefix, $name, $namespace, $writer->startElement($name); } if ($value !== null && strpbrk($value, '<>&')) { - $writer->writeCData($value); + $this->writeSafeCData($writer, $value); } else { $writer->writeRaw($value); } $writer->endElement(); } + protected function writeSafeCData(\XMLWriter $writer, $value) + { + $parts = explode(']]>', $value); + $last = array_pop($parts); + + foreach ($parts as $part) { + $writer->writeCData($part.']]'); + $writer->writeCData('>'); + } + + if ($last !== '') { + $writer->writeCData($last); + } + } + /** * Create a new xml writer and start a document *
tests/RequestLocation/XmlLocationTest.php+53 −0 modified@@ -524,4 +524,57 @@ public function testSerializesXml(array $operation, array $input, $xml) $this->assertEquals($xml, $body); } } + + /** + * @group RequestLocation + */ + public function testSplitsCDataTerminatorsToPreventXmlInjection() + { + $payload = 'x]]></Foo><Injected attr="1"/><Foo><![CDATA[y'; + $document = simplexml_load_string($this->serializeXmlValue($payload)); + + $this->assertNotFalse($document); + $this->assertCount(1, $document->Foo); + $this->assertCount(0, $document->Injected); + $this->assertSame($payload, (string) $document->Foo); + } + + public function cdataTerminatorProvider() + { + return [ + ['a]]>b'], + ['abc]]>'], + [']]>'], + ]; + } + + /** + * @dataProvider cdataTerminatorProvider + * + * @group RequestLocation + */ + public function testPreservesTextContainingCDataTerminators($value) + { + $document = simplexml_load_string($this->serializeXmlValue($value)); + + $this->assertNotFalse($document); + $this->assertSame($value, (string) $document->Foo); + } + + private function serializeXmlValue($value) + { + $location = new XmlLocation(); + $command = new Command('foo', ['Foo' => $value]); + $request = new Request('POST', 'http://httbin.org'); + $param = new Parameter([ + 'name' => 'Foo', + 'location' => 'xml', + 'type' => 'string', + ]); + + $location->visit($command, $request, $param); + $request = $location->after($command, $request, new Operation()); + + return (string) $request->getBody(); + } }
Vulnerability mechanics
Root cause
"Missing sanitization of the CDATA terminator `]]>` in XML request serialization allows attacker-controlled input to close the CDATA section early and inject arbitrary XML markup."
Attack vector
An attacker supplies a string containing the CDATA terminator `]]>` as a value for a `location: xml` request parameter (e.g., `DisplayName`). The vulnerable serializer wraps the value in a CDATA section, but the embedded `]]>` closes the CDATA early, and the remainder of the string is interpreted as raw XML markup. This allows the attacker to inject arbitrary XML elements (e.g., `<Role>admin</Role>`) into the outgoing request body, potentially altering operation semantics or smuggling privileged fields [ref_id=1][ref_id=2].
Affected code
The vulnerability is in `src/RequestLocation/XmlLocation.php` in the `writeElement()` method. When a scalar XML element value contains `<`, `>`, or `&`, the method calls `XMLWriter::writeCData($value)` without sanitizing the CDATA terminator `]]>`. The patch introduces a `writeSafeCData()` helper that splits the value on `]]>` and writes each segment safely.
What the fix does
The patch in `XmlLocation.php` replaces the direct `$writer->writeCData($value)` call with a new `writeSafeCData()` method. This method splits the input on the `]]>` terminator, writes each part as a separate CDATA section (rejoining the terminator across two CDATA blocks), and thereby prevents premature closure of the CDATA section [patch_id=5594252]. The fix preserves the original scalar value exactly and prevents injection of arbitrary XML nodes.
Preconditions
- configThe application uses guzzlehttp/guzzle-services to serialize outgoing requests.
- configA request parameter or additionalParameters schema uses location: xml.
- configThe value is serialized as XML element text (not an XML attribute).
- inputThe value contains attacker-controlled input that is not constrained by a safe enum, pattern, or filter excluding ]]>.
- networkThe downstream service parses the generated XML structurally and may act on injected elements.
Generated on Jun 11, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
2News mentions
0No linked articles in our index yet.