This is an automated email from the ASF dual-hosted git repository. Croway pushed a commit to branch fix/http-streaming-jail-starting-directory in repository https://gitbox.apache.org/repos/asf/camel-spring-boot-examples.git
commit edeaa8741c276111c6b6ff95e683103d83060a22 Author: croway <[email protected]> AuthorDate: Thu Sep 3 19:25:58 2026 +0200 Fix http-streaming upload example: restore file writes broken by Camel's jailStartingDirectory hardening Camel 4.23 hardened the file component's jailStartingDirectory containment check to unconditionally reject any starting directory whose compacted path still begins with "..", which is always true for the upload backend's `file:../client` endpoint. This made the upload scenario throw IllegalArgumentException on every request while the download scenario (which reads via plain java.io.File) kept working. Disable the check on this specific endpoint via jailStartingDirectory=false, since the target file name is a hardcoded constant and not derived from exchange/header data, so there is nothing here for the guard to protect against. Document the reasoning and the security trade-off in the example's README so it isn't copied blindly into routes with dynamic file names. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01R7ZfDGqU16yJFWuGogJ3Ju --- http-streaming/README.adoc | 22 ++++++++++++++++++++++ .../streaming/HttpStreamingCamelServerRouter.java | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/http-streaming/README.adoc b/http-streaming/README.adoc index a050c4ff..7c48c439 100644 --- a/http-streaming/README.adoc +++ b/http-streaming/README.adoc @@ -51,6 +51,28 @@ Follow these steps to run the example: Camel Spring Boot should process the HTTP byte stream and dump it in a file in the 'client' directory. +=== A note on `jailStartingDirectory` + +The upload backend writes the received stream with `to("file:../client?fileName=output&jailStartingDirectory=false")`. + +`jailStartingDirectory` is Camel's built-in path-traversal guard for `file:` endpoints: enabled by default, it refuses +to read/write any resolved path that falls outside the endpoint's configured starting directory, which is what stops +a crafted `CamelFileName` header from writing (or reading) files outside that directory via `../` sequences. + +It is disabled here only because the starting directory itself (`../client`) is expressed as a `..`-relative path, +which Camel's containment check now unconditionally rejects regardless of destination -- there was no way to keep the +check enabled without also changing how the target directory is expressed. That's safe in this example specifically +because the written file name (`output`) is a hardcoded constant, never derived from exchange or header data, so +there is nothing here for the check to actually protect against. + +[IMPORTANT] +==== +Do not copy `jailStartingDirectory=false` into routes where the file name (or the directory) is derived from +exchange data, headers, or any external input. Doing so reopens the exact path-traversal risk the option exists to +prevent. Keep the default (`true`) in that case, and resolve the target directory to an absolute/canonical path +instead of a `..`-relative one, so the containment check stays active and meaningful. +==== + === Help and contributions If you hit any problem using Camel or have some feedback, then please diff --git a/http-streaming/upload/backend-server/src/main/java/org/apache/camel/springboot/example/http/streaming/HttpStreamingCamelServerRouter.java b/http-streaming/upload/backend-server/src/main/java/org/apache/camel/springboot/example/http/streaming/HttpStreamingCamelServerRouter.java index 09b14f8e..e0e7f650 100644 --- a/http-streaming/upload/backend-server/src/main/java/org/apache/camel/springboot/example/http/streaming/HttpStreamingCamelServerRouter.java +++ b/http-streaming/upload/backend-server/src/main/java/org/apache/camel/springboot/example/http/streaming/HttpStreamingCamelServerRouter.java @@ -29,7 +29,7 @@ public class HttpStreamingCamelServerRouter extends RouteBuilder { .put("/test").to("direct:backend"); from("direct:backend") - .to("file:../client?fileName=output") + .to("file:../client?fileName=output&jailStartingDirectory=false") .log("done streaming") .setBody(constant("done")); }
