oscerd opened a new pull request, #26904:
URL: https://github.com/apache/camel/pull/26904

   CAMEL-24451: camel-xslt - honor ACCESS_EXTERNAL_STYLESHEET for runtime 
document()
   
   ## Background
   
   `XsltBuilder` always installs an `XsltUriResolver` (created by 
`DefaultXsltUriResolverFactory` in
   `XsltComponent`). JAXP consults a factory's `ACCESS_EXTERNAL_STYLESHEET` 
attribute only when **no**
   `URIResolver` returns a `Source`, so the always-installed resolver resolved 
external `http:`,
   `https:`, `ftp:` and `file:` references at transform time regardless of that 
attribute.
   
   Camel's **default** XSLT transformer factory 
(`XMLConverterHelper.createTransformerFactory()`, in
   `camel-xml-jaxp`) sets `ACCESS_EXTERNAL_DTD=""` and 
`ACCESS_EXTERNAL_STYLESHEET=""` (deny-all). So
   the framework's own secure default was **silently bypassed** at runtime: a 
stylesheet that passes a
   parameter into the XPath `document()` function could read an attacker-chosen 
external resource,
   because every message header (including headers arriving from the wire) is 
bound as a stylesheet
   parameter. This is the same shape as CAMEL-24427 — a configured control 
silently doing nothing.
   
   ## Change
   
   The resolver installed on the **transformer** (runtime `document()`) now 
honors the factory's
   `ACCESS_EXTERNAL_STYLESHEET`:
   
   - `""` (Camel's default) → deny all external protocols
   - a comma-separated list (`file`, `http,https`) → allow only those
   - `all` / unset / a factory that does not support the attribute → 
unrestricted (unchanged)
   
   A denied external reference resolves to an **empty document** (so 
`document()` yields an empty
   node-set instead of the resource content) and a warning is logged. Returning 
an empty `Source`
   - rather than throwing - guarantees the processor does not fall back to its 
own resolution and read
   the resource anyway.
   
   **Scope (deliberately runtime-only):**
   - **Runtime `document()`** (untrusted, header-influenceable) → now governed. 
✅
   - **Compile-time `xsl:include` / `xsl:import`** (the route author's own 
stylesheet) → the resolver
     installed on the *factory* is left unrestricted, so these are unchanged. ✅ 
Route authors are fully
     trusted, so their own includes are intentionally not restricted (and 
existing behavior/tests are
     preserved).
   
   `ACCESS_EXTERNAL_DTD` is enforced by the XML parser's `EntityResolver`, 
which the component does not
   override unless one is configured, so it already applies on its own and is 
untouched here.
   
   ## Behavior change (default) — for maintainers / PMC
   
   This tightens a default: an external `document()` over 
`file:`/`http:`/`https:`/`ftp:` is refused by
   default. To opt back in, supply a custom `TransformerFactory` (via 
`transformerFactory`) whose
   `ACCESS_EXTERNAL_STYLESHEET` permits the required protocols. Documented in 
the component page and the
   4.23 upgrade guide.
   
   Note on the original issue: the first proposed change (gating 
header→parameter binding off by
   default) was rejected earlier as it breaks documented behavior. This PR 
implements the second piece
   (resolver honors the factory limit) plus documentation. The earlier "no 
Camel-configured restriction
   is being defeated" note was based on a `camel-xslt`-scoped search; the 
restriction is in fact set in
   `camel-xml-jaxp` and **is** defeated at runtime — so this is a real (if 
low-severity) fix.
   
   ## Public API (camel-xslt)
   
   Additive, backward-compatible: `XsltUriResolver` gains a 3-arg constructor
   `(CamelContext, String, Set<String>)`, 
`withAllowedExternalProtocols(Set<String>)`, and a static
   `parseAllowedProtocols(String)`. The existing 2-arg constructor is preserved 
(delegates to
   unrestricted).
   
   ## Tests (camel-core, as camel-xslt has no test tree)
   
   - `XsltUriResolverExternalAccessTest` (resolver unit): deny-all / allow-list 
return the empty denied
     document; an allowed protocol and internal `classpath:` proceed to real 
resolution;
     `parseAllowedProtocols`.
   - `XsltDocumentExternalAccessTest` (end-to-end): a default `xslt:` route 
does not read
     `document('file:…')` given via a header parameter; a route with a factory 
permitting `file` does.
   - Existing `XsltInclude*` tests (compile-time `file:` include) still pass — 
compile path unchanged.
   - Revert-to-red verified on both the resolver enforcement and the builder 
wiring.
   
   ## Docs
   
   - `xslt-component.adoc` ("Getting Usable Parameters into the XSLT"): 
untrusted headers bound as
     parameters reach `document()`; `removeHeaders` mitigation; default 
external-access deny + opt-back-in.
     (catalog copy regenerated)
   - `camel-4x-upgrade-guide-4_23.adoc`: the default behavior change and how to 
relax it.
   
   
   🤖 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]

Reply via email to