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]