The GitHub Actions job "Java CI" on commons-xml.git/main has failed.
Run started by GitHub user ppkarwasz (triggered by ppkarwasz).

Head commit for run:
bfa4a5a1155575dc7531e54f32a5dccbe1957a91 / Piotr P. Karwasz 
<[email protected]>
COMMONSXML-1: DocumentBuilderFactory: capability-driven hardening (#5)

* Base DocumentBuilderFactory hardening on feature support

This change replaces the per-implementation class-name dispatch for DOM with a 
single capability-driven recipe. Secure processing is required and the 
external-DTD subset is skipped where supported; whether the JAXP 1.5 
accessExternal properties are honoured then decides whether the bare factory is 
already safe or needs a deny-all resolver wrapper, which is the only point 
where the stock JDK and the external Xerces distribution diverge. Android stays 
untouched because its parser exposes no hardening surface.

An implementation is no longer rejected for being unrecognised. Any parser that 
accepts secure processing and either the access properties or the resolver 
wrapper satisfies the contract on its own, so only a parser that refuses secure 
processing now fails.

A new test covers the previously unverified guarantee that an 
xsi:schemaLocation hint is not fetched during DOM-side XSD validation, gated on 
parsers that honour accessExternalSchema.

Assisted-By: Claude Opus 4.8 <[email protected]>

* Add minimal-footprint DocumentBuilderHardener.newInstance() entry point

Expose DocumentBuilderHardener with a public newInstance() so consumers that
only need a hardened DocumentBuilderFactory can shade the library and copy a
minimal set of classes. jdependency (the engine maven-shade-plugin's
minimizeJar uses) works at class granularity, so the shaded set is the
transitive closure of this one class.

To keep that closure small, install a deny-all EntityResolver as a lambda
local to DocumentBuilderHardener instead of reusing Resolvers.DenyAll.ENTITY2.
EntityResolver's resolveEntity(publicId, systemId) hook is consulted for the
external DTD subset and every external entity, so it blocks all external
fetches on the DOM path just as well, while dropping the whole Resolvers
nested-class tree from the closure (12 -> 7 class files).

Route XmlFactories.newDocumentBuilderFactory() through the new entry point, and
add ShadingFootprintTest, which uses jdependency to pin the reachable set to
exactly those 7 classes so the footprint cannot silently grow back toward the
full library.

Assisted-By: Claude Opus 4.8 (1M context) <[email protected]>

* fix: keep `DelegatingDocumentBuilderFactory` a top-level class

* Fix Android test compilation

The androidTest source set compiles all of ../src/test/java against
android.jar, which broke on two tests new to this branch:

- ShadingFootprintTest needs org.vafer.jdependency (a Maven-only test
  dependency) and pins the shading footprint, which is meaningless on
  Android. Exclude it from the Android test compilation.

- SchemaLocationDomTest referenced XMLConstants.ACCESS_EXTERNAL_SCHEMA,
  which android.jar does not expose. Inline the constant's value
  (verified equal to the JDK constant); the test still skips at runtime
  on Android, since the parser does not honour that property.

Verified on the api33 (Pixel 6a) managed device: 77 tests, 0 failures,
0 errors, 17 assumption-gated skips.

Assisted-By: Claude Opus 4.8 (1M context) <[email protected]>

* Gate SchemaLocationDomTest on schema-language support, not 
accessExternalSchema

The test exercises JAXP 1.2 XSD validation, which requires the SCHEMA_LANGUAGE
property; that, not accessExternalSchema, is the capability a parser must have
to run it (Android lacks it). Gate both methods on supportsSchemaLanguage().

The hardened assertion also assumed the block was attributed to
accessExternalSchema, which only holds on the stock JDK. External Xerces does
not honour that property and instead blocks the schema fetch through the
deny-all resolver, with a different message. Assert only that the failure
references the external schema, not the mechanism.

Two effects:
- The test now runs and passes on external Xerces too (covering the
  resolver-based schema-block path), where it previously skipped.
- It no longer references XMLConstants.ACCESS_EXTERNAL_SCHEMA, so the
  android.jar compile gap is resolved by this redesign rather than by
  inlining the constant.

Verified: mvn -o test green across all executions; SchemaLocationDomTest runs
2/2 with 0 skips on both stock JDK and external Xerces.

Assisted-By: Claude Opus 4.8 (1M context) <[email protected]>

* Remove the minimal-footprint shading entry point from this PR

Split per review: this PR (COMMONSXML-1) keeps only the capability-driven
DocumentBuilderFactory hardening. The minimal shading entry point (public
DocumentBuilderHardener.newInstance(), the inlined deny-all resolver,
ShadingFootprintTest and the jdependency test dependency) will be filed as
its own issue.

Reverses 68ad1d1 and 90ef0ae: DocumentBuilderHardener is package-private
again and harden() reuses Resolvers.DenyAll.ENTITY2;
XmlFactories.newDocumentBuilderFactory() calls harden() directly.

Assisted-By: Claude Opus 4.8 (1M context) <[email protected]>

* fix: apply review suggestions

Report URL: https://github.com/apache/commons-xml/actions/runs/28297146181

With regards,
GitHub Actions via GitBox

Reply via email to