ppkarwasz opened a new pull request, #30: URL: https://github.com/apache/commons-xml/pull/30
Stacked on #28 (`feature/reduce-shade-footprint`); only the three commits above that branch belong to this PR. ## Why The deny-all resolver floors rejected every unresolved external reference with an exception, so a document that merely carries a DOCTYPE (without needing anything from it) failed to parse. Resolving unresolved references to empty content keeps the identical security property, nothing is fetched and nothing leaks, while letting such documents parse. The ignore outcome is best-effort: where an implementation prescribes a rejection (XSLTC and Xalan reject an emptied `xsl:import` module at compile time, Xerces treats an entity declared in an emptied subset as undeclared and fatal), the block remains an acceptable outcome and tests assert "blocks or does not leak". ## What 1. **Make the resolver floors ignore-all instead of deny-all.** The four floors resolve unresolved lookups to empty content and are renamed `FallbackDeny*` to `FallbackIgnore*`. The deny/ignore split made several variants redundant (`DtdAwareDenyResolver`, `DtdSubsetFloor`, the old Woodstox-only `FallbackIgnoreXMLResolver`, `HardeningException.forbidden`); removing them takes the shade closure from 33 to 30 classes. The StAX floor collapses into the `HardeningXMLInputFactory` constructor, with a single `setXMLResolver` covering both the JDK Zephyr and Woodstox. 2. **Drop `XERCES_LOAD_EXTERNAL_DTD` from the hardening recipes.** Skipping the external DTD subset up front is redundant once the floor resolves it to empty. Actually requesting the subset exposed two gaps, fixed here: the floors now echo the requested identifiers on the empty source they return (Xerces derives the entity's base URI from the system id and fails on null), and the LSResourceResolver floor hands its content over as a character stream because the JDK's `DOMEntityResolverWrapper` discards empty string data. 3. **Extend the ignore-all floor to Saxon resource resolution.** Saxon's `ALLOWED_PROTOCOLS=""` lockdown was the odd one out, rejecting instead of ignoring. It is replaced by a nature-aware ignore-all `ResourceResolver` on the `HardenedConfiguration` (`EmptySource` for XML/XSLT/XSD natures, an empty `StreamSource` for text, `null` for entity/DTD natures so the lookup falls through to the hardened reader's floor and caller allow-listing keeps working), made non-removable by a `setResourceResolver` override (plain-JAXP `TransformerFactory.setURIResolver` replaces the Configuration resolver wholesale), plus `CollectionFn.EMPTY_COLLECTION` for `fn:collection`, the one channel that bypasses the resolver. ## Testing Full surefire matrix green (stock JDK, Xerces, Xalan, Xalan+Xerces, Saxon, Saxon+Xerces, Woodstox). Tests that asserted an exception now assert the external resource does not leak; where implementations diverge they accept either outcome through the `assert*BlocksOrDoesNotLeak` helpers. Saxon now passes the DOCTYPE-only and external-DTD suites identically to the other stacks. 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
