Last reviewed: October 31, 2026 (Asia/Shanghai). Sources fetched October 30, 2026 UTC.

Direct answer

Prevent XML external entity injection (XXE) in coding-agent patches by deciding what resources an XML processor may access before it reads untrusted bytes. Reject document type declarations when the feature does not need DTDs, disable external entity and external DTD loading, keep XInclude disabled, and restrict external resources separately during schema validation and transformation. Treat an unsupported required security setting as a configuration failure. Test the actual processing path for attempted file reads and network requests, including cases where parsing eventually returns an error.

Consider an agent-written import route that parses a document, validates its fields, and then saves a record. A parser can resolve an external entity while building the document, before the field checks run. MITRE’s CWE-611 definition describes XML references escaping the intended sphere of control and identifies file disclosure, unintended outbound requests, and resource exhaustion as possible consequences. Rejecting the final record cannot undo a request already sent.

The acceptance rule is concrete: one approved document produces the expected data; disallowed references produce no resource access and no business side effect. The parser, validator, transformer, resolver, and input-opening code must all satisfy that rule.

Who this is for

Use this review when a coding agent changes XML imports, SOAP clients, document converters, metadata readers, configuration loaders, SVG processing, or libraries that parse XML internally. Inspect wrappers as well as direct parser calls. The Java examples below target the JDK’s built-in JAXP implementation; other providers and languages need their own documented settings and tests.

This review complements the site’s SSRF review for URL fetchers because a parser can initiate requests without an explicit HTTP call in the diff. Follow the file-upload boundary review for request limits, private staging, and promotion of uploaded XML. The specific question here is which references the XML processing pipeline can resolve.

Key takeaways

  • Reject DOCTYPE declarations when DTDs are unnecessary; do not rely on checking the parsed tree afterward.
  • Keep XInclude disabled and review schema imports, stylesheet includes, and transformation functions independently.
  • Supply an already authorized, bounded input stream. External-entity restrictions do not authorize an initial filename or URL.
  • Configure the implementation that actually reads the document, before creating or invoking the processor.
  • Make required configuration failures fatal to that processing path; never retry with a permissive parser.
  • If dependencies are essential, map exact approved identifiers to application-owned resources and reject unknown identifiers.
  • Assert absence of I/O and downstream writes in negative tests. An exception alone is weak evidence.
  • Add byte, depth, expansion, memory, and execution limits. Preventing XXE does not eliminate other XML resource risks.

Sources checked

Three primary references were fetched successfully on October 30, 2026 UTC:

These are maintained technical references for an evergreen review, not evidence of a newly discovered exploit. Oracle’s guide is version-specific: compare its settings with the JDK and provider actually deployed. The acceptance contract and test workflow below are recommendations. The illustrative code has not been executed here, and no repository or deployment result is claimed.

Contract details to verify

Map every stage that can load a resource

Trace the input from receipt to final output. Record the parser factory and provider, every validation or transformation step, resolver callbacks, catalog files, and any later reparse. Search for DOM and SAX builders, StAX factories, SchemaFactory, Validator, TransformerFactory, XPath input overloads, and unmarshalling wrappers.

OWASP notes that initial input acquisition is separate from external entity resolution. Passing an untrusted URL to parse(...) still asks the application to open that URL, even when external entities are blocked. Open an authorized object through the application’s reviewed storage or fetch layer, enforce its byte limit, and pass the resulting stream. Give the caller responsibility for closing that stream.

BoundaryDecision to recordEvidence required
Initial inputAuthorized object and maximum bytesControlled stream acquisition; oversized input rejected
DTDs and entitiesRejected, or narrowly requiredEffective parser settings and disallowed-reference tests
XIncludeDisabled unless explicitly requiredNo implicit include-processing step; inclusion fixture
SchemasApplication-owned schema and dependency policyRestricted compilation and validation
StylesheetsApplication-owned stylesheet and dependency policyRestricted compilation and transformation
Resolvers and catalogsExact approved identifiers; unknowns deniedKnown dependency succeeds; unknown dependency cannot fall through
Resource useDepth, expansion, size, memory, timePositive finite limits and isolated boundary tests

Do not let document-supplied schema locations or stylesheet instructions choose an application dependency. A trusted top-level schema can also import another resource, so inspect its dependency closure and configure restrictions before compiling it.

Configure the actual parser before use

For a feature that needs ordinary XML without DTDs, a narrow DOM configuration is easier to review than a collection of compatibility exceptions. This illustrative fragment follows the JDK built-in approach documented by OWASP and Oracle:

DocumentBuilderFactory factory =
    DocumentBuilderFactory.newDefaultInstance();
factory.setNamespaceAware(true);
factory.setFeature(
    "http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setXIncludeAware(false);
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");

DocumentBuilder builder = factory.newDocumentBuilder();
builder.setEntityResolver((publicId, systemId) -> {
    throw new SAXException("xml_external_reference_denied");
});
Document document = builder.parse(boundedAuthorizedStream);

Imports, stream acquisition, application-specific limits, and error handling are omitted. boundedAuthorizedStream must be supplied by reviewed application code; the identifier itself does not impose a bound. Required configuration calls must succeed before the builder is used. Map configuration failures to an unavailable XML-processing path rather than catching them and continuing. Install a non-logging parser error handler before parsing and translate failures into sanitized application codes; catching an exception afterward does not suppress diagnostics already emitted by a lower layer.

Do not generalize this fragment to every provider. newDefaultInstance() selects the JDK built-in implementation; provider lookup through newInstance() can select something else. OWASP also warns that setExpandEntityReferences(false) controls tree representation and must not substitute for external-resource restrictions.

Oracle distinguishes secure processing enabled by default from explicitly enabling it through the API: default FSP does not itself disable external connections. Keep the intended external-access policy explicit and verify it on the deployed runtime. StAX does not support FSP; OWASP instead documents disabling both SUPPORT_DTD and IS_SUPPORTING_EXTERNAL_ENTITIES, with a rejecting resolver. Disabling DTD processing is not necessarily the same as rejecting the DOCTYPE declaration.

Harden validation, transformation, and resolution

A secure DOM builder does not configure a later processor that reparses raw XML. OWASP recommends restricting ACCESS_EXTERNAL_DTD and ACCESS_EXTERNAL_SCHEMA on SchemaFactory before compiling an application-owned schema. For an application-owned stylesheet, restrict ACCESS_EXTERNAL_DTD and ACCESS_EXTERNAL_STYLESHEET on TransformerFactory before compilation. Stylesheet imports, includes, and document() can load resources independently of entity expansion. These settings do not make arbitrary untrusted stylesheets safe to execute.

When dependencies are required, prefer an exact mapping from approved identifiers to packaged local bytes. Use a strict catalog or an allowlisting resolver that rejects unknown identifiers. Returning null from relevant resolver callbacks can delegate to default resolution; it is not a reliable denial. For Java validation, OWASP specifically notes that validators do not inherit the factory’s resolver, so install the intended resolver on the factory and each validator.

Oracle explains that external-access properties restrict protocols, not individual resources, and that they do not control sources returned by a non-null resolver result. Allowing https therefore does not authorize a particular host or file. Review the resolver’s own resource-opening code. A resolver that downloads arbitrary input-selected URLs recreates the original authority problem behind a callback.

Bound work independently of external access

Retain request and decompressed-byte limits, then set processor limits for document depth, attribute count, entity expansion, and other applicable structures. Oracle documents positive integer processing limits and warns that a value of zero or below means no limit. Avoid copying zero into a configuration as a supposed strict setting.

Choose limits from legitimate fixtures and the deployment’s resource budget. Run expensive rejection cases in a disposable worker with an outside deadline and a memory cap. External access can be fully disabled while a document still consumes unacceptable CPU or memory. Keep that resource gate separate from the assertion that no reference was resolved.

Build a harmless adversarial test matrix

Use synthetic XML, a temporary file containing a random non-secret marker, and an isolated local fixture server. Observe resolver decisions, fixture-server request counts, and file-open attempts using appropriate runtime or sandbox instrumentation. The harness should first demonstrate that it can observe an intentional controlled read and request. Then reset its counters before testing the hardened path. Do not use machine secrets, cloud metadata addresses, or real internal services.

FixtureRequired observation
Minimal approved XMLExpected data and exactly one intended business operation
DOCTYPE with only an internal declarationRejected when the contract forbids DTDs; no business write
External general or parameter entity; external DTDNo fixture-file read or server request; controlled rejection
XInclude referencing the fixtureNo resource load; contract rejects the construct or leaves it inert
Unapproved schema import or includeCompilation or validation fails without external I/O
Unapproved stylesheet dependency or document() accessNo resource load during compilation or transformation
Known packaged dependency and unknown identifierKnown mapping works; unknown identifier fails without fallback
Oversized, deep, or expansion-heavy documentBounded rejection and complete worker cleanup
Unsupported required security settingProcessor never starts; no permissive fallback
Error after partial parseNo database commit, output promotion, or raw parser diagnostic in public logs

Exercise the actual production entry point, including libraries that internally create processors. A mock resolver tests application branching but cannot establish that a different parser instance is hardened. If XInclude markup is retained as inert data, confirm that no downstream library later activates it. Test each deployed provider and repeat the matrix when a runtime, dependency, catalog, or parser wrapper changes.

For file references, absence of the marker in the response is insufficient: the parser might read it and fail later. For network references, a final connection error may prove an attempted request rather than successful denial. Retain the observation method and event ordering with the result.

Happy-path operator workflow

  1. Identify the changed entry point, authorized input source, runtime, provider, and complete processing chain.
  2. Write whether DTDs, XInclude, schemas, stylesheets, and external dependencies are allowed.
  3. Configure every factory, processor, and resolver before compilation or parsing; stop on unsupported required settings.
  4. Acquire a bounded authorized stream and keep schemas, stylesheets, and catalogs under application control.
  5. Run the valid fixture, verify the exact data result, then run the disallowed-reference and resource-limit cases.
  6. Confirm no forbidden I/O occurred and only fully validated data reached persistence or output promotion.
  7. Attach the policy revision, runtime and provider versions, fixture IDs, observed access counts, terminal codes, and cleanup result to the review.

Error-path operator workflow

Separate configuration failure, malformed XML, denied references, schema failure, resource exhaustion, and worker timeout. Suggested application codes include xml_configuration_invalid, xml_reference_denied, xml_invalid, and xml_limit_exceeded. They are proposed operational labels, not standardized parser messages.

Stop the pipeline after failure. Discard partial trees and staged output, roll back uncommitted business changes, close input resources, and terminate an over-budget worker. Do not remove the DOCTYPE and retry, fetch a missing dependency automatically, or switch to a default parser to preserve availability. A compatibility exception requires a reviewed dependency policy and new tests.

Return a controlled error without raw XML, file paths, system identifiers, or parser exception text. Record the policy revision, stage, fixture or request ID, size bucket, provider, stable reason code, and cleanup status. Parser errors can repeat attacker-controlled identifiers or sensitive content.

Failure modes

The patch validates fields after parsing. Resolution can already have happened. Apply parser policy first and assert zero forbidden access.

One hardened builder exists, but another wrapper reads the bytes. Trace the effective call path, including validators, XPath input overloads, and unmarshalling helpers.

A protocol restriction is called an allowlist. Permitting file or https does not identify approved resources. Use exact dependency mappings and review the resolver itself.

Only external entities are disabled. XInclude, schema dependencies, and stylesheet operations need their own controls.

A rejected document is assumed to have caused no side effects. Inspect attempted I/O and database or output events before the error.

The agent silences a security-setting exception. Partial configuration is not the approved policy. Keep that processor unavailable until configuration succeeds.

FAQ

Is blocking DOCTYPE enough?

It removes the DTD-based route when the actual parser enforces it. It does not authorize the initial input URL, configure XInclude, or secure later validation and transformation. Review the whole chain.

Can XML schemas make an unsafe parser safe?

Schema validation does not undo resource access that occurred while parsing. Schema compilation and validation can also resolve dependencies, so configure both stages before using them.

What if a legacy format needs a DTD?

Define the exact required identifiers, supply reviewed local resources through a strict catalog or resolver, block fallback access, and retain expansion limits. Test known and unknown dependencies on the deployed provider.

Does a no-network container solve XXE?

It limits network impact, but readable local files and resource exhaustion remain relevant. Keep parser restrictions, minimal filesystem authority, and resource budgets as independent controls.

Reader next step

Choose one XML entry point in the next coding-agent patch. Draw its parser, validator, transformer, and resolver chain, then add a valid document plus a harmless external-reference fixture for each applicable stage. Require evidence of zero forbidden resource access and zero business writes on rejection. Keep the patch blocked if a required setting fails, an unknown dependency falls through, or an error conceals an earlier side effect. Use the file-upload boundary review to connect those parser checks to staging and promotion.