zhfeng commented on code in PR #9116:
URL: https://github.com/apache/camel-quarkus/pull/9116#discussion_r3939917702
##########
extensions-support/xalan/runtime/src/main/java/org/apache/camel/quarkus/support/xalan/XalanTransformerFactory.java:
##########
@@ -138,12 +198,224 @@ public TemplatesHandler newTemplatesHandler() throws
TransformerConfigurationExc
@Override
public XMLFilter newXMLFilter(Source source) throws
TransformerConfigurationException {
- return delegate.newXMLFilter(source);
+ return secure(delegate.newXMLFilter(source));
}
@Override
public XMLFilter newXMLFilter(Templates templates) throws
TransformerConfigurationException {
- return delegate.newXMLFilter(templates);
+ return secure(delegate.newXMLFilter(unwrap(templates)));
+ }
+
+ /**
+ * The SAX push entry points hand the caller a {@link Transformer} to
configure rather than one to call,
+ * and Xalan only copies the factory's {@link URIResolver} onto some of
them, so {@code document()} is
+ * restricted here for the same reason it is in {@link
#secure(Transformer)}. The document being
+ * transformed is parsed by the {@link XMLReader} the caller drives the
handler with, which is the
+ * caller's own choice just as a {@link SAXSource} carrying a reader is.
+ */
+ private TransformerHandler secure(TransformerHandler handler) {
+ handler.getTransformer().setURIResolver(restrictingUriResolver);
+ return handler;
+ }
+
+ /**
+ * {@link XMLFilter} has no accessor for the {@link Transformer} behind
it, so the restriction can only be
+ * installed on Xalan's own implementation. Guarded rather than cast
blindly so that a Xalan upgrade
+ * returning something else is reported instead of silently dropping the
restriction.
+ */
+ private XMLFilter secure(XMLFilter filter) {
+ if (filter instanceof TrAXFilter) {
+ ((TrAXFilter)
filter).getTransformer().setURIResolver(restrictingUriResolver);
+ } else {
+ LOGGER.warn("Expected an {} from the Xalan TransformerFactory but
got {}. The document() function"
+ + " may resolve external resources when transforming
through this XMLFilter.",
+ TrAXFilter.class.getName(), filter == null ? null :
filter.getClass().getName());
+ }
+ return filter;
+ }
+
+ /**
+ * Xalan casts {@link Templates} to its own {@code TemplatesImpl}
internally, so the wrapper has to be
+ * peeled off before handing one back to the delegate.
+ */
+ private static Templates unwrap(Templates templates) {
+ return templates instanceof SecuredTemplates ? ((SecuredTemplates)
templates).delegate : templates;
+ }
+
+ /**
+ * Parses {@code source} with a hardened {@link XMLReader} unless it has
already been parsed, or the
+ * caller supplied its own reader. Mirrors what {@code
XmlConverter.createSAXParserFactory()} does for
+ * the bodies camel-xslt converts itself, so that {@link Source}-shaped
bodies get the same treatment.
+ */
+ private static Source secureInputSource(Source source) throws
TransformerException {
+ if (source instanceof StreamSource) {
+ final StreamSource streamSource = (StreamSource) source;
+ final InputStream inputStream = streamSource.getInputStream();
+ final Reader reader = streamSource.getReader();
+ if (inputStream == null && reader == null) {
+ // Nothing but a systemId; let the delegate resolve it as
before
+ return source;
Review Comment:
A system-ID-only `StreamSource` bypasses the hardened parser here. For
example, `new StreamSource(input.toUri().toString())` has neither an input
stream nor a reader, so this returns the source unchanged and lets Xalan open
and parse the document with its own parser. If that document contains a
`SYSTEM` entity, the `XMLReader` configured above with external general
entities disabled is never used, and the entity may still be resolved.
Could this branch instead construct an `InputSource` with the system ID and
return `new SAXSource(createSecureXmlReader(), inputSource)`? That preserves
loading of the primary document and its base URI while ensuring it is parsed by
the secured reader. A regression test using a system-ID-only `StreamSource`
containing the external entity would cover this path.
--
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]