September 26, 2018·4 min read·engineeringpythonxmlsecurity

Python 3.7.1rc1 changes the default treatment of external XML entities

The first Python 3.7 maintenance candidate disables default external-entity processing in selected XML parsers. It also repairs compatibility details in dataclasses and the contextvars C API.

Parsing a document can cause work outside the document itself. An external XML declaration can refer to a file or a network resource, so a parser's default behaviour determines whether reading supplied text also permits access to other locations. Python 3.7.1rc1 changes that default in selected standard-library parsers.

The September 26 release announcement identifies this as the first candidate for Python 3.7's first maintenance release. It remains a preview, with production use discouraged. The changelog pinned to the candidate records a security change for xml.sax and xml.dom.minidom, which no longer process external entities by default. External DTD and entity declarations no longer load files or create network connections under those defaults.

I rely on Python's libraries because they often remove substantial implementation work. That makes their defaults part of the application's design. A caller asking a parser to read a document needs to know whether that request also authorizes filesystem and network activity.

The default controls access beyond the input

The change identified as bpo-17239 affects what happens without an application explicitly choosing external-entity processing. This is a useful security boundary because it separates the supplied document from resources named by that document. The input's author should not acquire unrelated access merely because a library supports a richer document format.

There is also a compatibility consequence. A program whose documents rely on the old default can observe different results after a runtime update. The entry does not justify a claim that every XML parser changes or that every XML document is affected. It names two parser interfaces and one class of behaviour. Maintaining that specificity matters when deciding what existing code depends on.

The release-candidate stage gives maintainers an opportunity to examine that dependency before the maintenance release becomes final. A document that contains all the information it needs differs from one that expects a parser to retrieve an external declaration. Both may be valid inputs in the application's terms, but their execution requirements differ.

This also shows why a patch release can carry behaviour changes that deserve more than a version-number check. Disabling an unsafe default preserves the broad purpose of the parsing API while changing an operation that some callers may have relied upon. Compatibility work needs to examine that behaviour directly, rather than assuming unchanged function names imply unchanged resource access.

XML hash initialization receives a separate repair

The candidate changelog also identifies CVE-2018-14647 in the accelerated _elementtree module. It changes hash-randomization salt initialization to use _Py_HashSecret instead of Expat's default generator. This is a separate correction from external-entity handling, despite both entries involving XML processing.

This distinction helps establish what an update actually does. External entities concern resource access triggered by declarations. The salt change concerns initialization inside the accelerated parser implementation. An application using one XML interface cannot infer its precise exposure merely from a release summary that says XML security has improved. Module choice and build composition determine which implementation the application actually calls during document processing.

The same notes update the vendored Expat copy to 2.2.6. That is a statement about the code bundled in this source release. It should remain distinct from claims about the libraries linked by a particular distributor's runtime. The candidate's own source and the installed interpreter's construction are related evidence, but they are not interchangeable descriptions.

New Python 3.7 facilities need compatibility work too

The candidate includes a correction to the contextvars C API, changing its pointer types to PyObject*. Extension authors using that API have a concrete reason to examine the candidate's headers and their own call sites. The entry concerns the native interface, so a Python-only application example would not adequately describe the affected contract.

Data-class conversion also receives a correction. The notes say dataclasses.asdict() and astuple() now handle named tuples correctly. Those helpers combine the new data-class model with an established record representation. Interoperability between them matters to libraries that accept existing objects inside new data classes.

A further fix allows a frozen data class to have a field named object, which previously conflicted with internal use of that name. The field declaration was application data, but generated implementation code accidentally gave the name additional significance. Correcting that conflict helps the generated methods respect the class author's declared field names.

My assessment of this candidate centres on these observable contracts. Parser defaults decide whether input can cause external access, and generated or native interfaces must preserve their documented meaning. The release supplies a specific candidate in which maintainers can inspect those changes while it is still explicitly a preview. No final-release outcome needs to be assumed to explain why those compatibility questions matter now.