fix(notifications): prohibit DTD processing in EwsResponseParser (XXE guard)

The review asked for a regression test pinning DTD-prohibited parsing. Writing
it showed the premise was wrong: XDocument.Parse permits an internal DTD subset
and expands its entities, so a DOCTYPE-bearing response body parsed fine and the
guard did not exist (entity-expansion DoS on external input).

Parse now goes through XmlReader with DtdProcessing.Prohibit and a null
XmlResolver. The regression test feeds a DOCTYPE + ENTITY payload shaped as a
well-formed EWS error response, so it fails if DtdProcessing is ever loosened
rather than passing for the unrelated-XML reason.
This commit is contained in:
Joseph Doherty
2026-08-10 06:20:48 -04:00
parent abc58e6394
commit 6864890e5f
2 changed files with 53 additions and 2 deletions
@@ -1,3 +1,4 @@
using System.Xml;
using System.Xml.Linq;
namespace ZB.MOM.WW.ScadaBridge.NotificationService.Ews;
@@ -64,9 +65,20 @@ public static class EwsResponseParser
XDocument document;
try
{
document = XDocument.Parse(responseBody);
// The body is external input, so DTDs are prohibited outright: LINQ-to-XML's own
// XDocument.Parse permits an internal DTD subset and expands its entities (verified),
// which is an entity-expansion DoS on a response body. A null resolver additionally
// blocks external entity/DTD fetches (XXE).
var settings = new XmlReaderSettings
{
DtdProcessing = DtdProcessing.Prohibit,
XmlResolver = null,
};
using var reader = XmlReader.Create(new StringReader(responseBody), settings);
document = XDocument.Load(reader);
}
catch (System.Xml.XmlException)
catch (XmlException)
{
return UnparseableResult;
}