Skip to content

Commit 9439c19

Browse files
Crowayclaude
andcommitted
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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R7ZfDGqU16yJFWuGogJ3Ju
1 parent 96a05b8 commit 9439c19

2 files changed

Lines changed: 23 additions & 1 deletion

File tree

‎http-streaming/README.adoc‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,28 @@ Follow these steps to run the example:
5151

5252
Camel Spring Boot should process the HTTP byte stream and dump it in a file in the 'client' directory.
5353

54+
=== A note on `jailStartingDirectory`
55+
56+
The upload backend writes the received stream with `to("file:../client?fileName=output&jailStartingDirectory=false")`.
57+
58+
`jailStartingDirectory` is Camel's built-in path-traversal guard for `file:` endpoints: enabled by default, it refuses
59+
to read/write any resolved path that falls outside the endpoint's configured starting directory, which is what stops
60+
a crafted `CamelFileName` header from writing (or reading) files outside that directory via `../` sequences.
61+
62+
It is disabled here only because the starting directory itself (`../client`) is expressed as a `..`-relative path,
63+
which Camel's containment check now unconditionally rejects regardless of destination -- there was no way to keep the
64+
check enabled without also changing how the target directory is expressed. That's safe in this example specifically
65+
because the written file name (`output`) is a hardcoded constant, never derived from exchange or header data, so
66+
there is nothing here for the check to actually protect against.
67+
68+
[IMPORTANT]
69+
====
70+
Do not copy `jailStartingDirectory=false` into routes where the file name (or the directory) is derived from
71+
exchange data, headers, or any external input. Doing so reopens the exact path-traversal risk the option exists to
72+
prevent. Keep the default (`true`) in that case, and resolve the target directory to an absolute/canonical path
73+
instead of a `..`-relative one, so the containment check stays active and meaningful.
74+
====
75+
5476
=== Help and contributions
5577

5678
If you hit any problem using Camel or have some feedback, then please

‎http-streaming/upload/backend-server/src/main/java/org/apache/camel/springboot/example/http/streaming/HttpStreamingCamelServerRouter.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public void configure() throws Exception {
2929
.put("/test").to("direct:backend");
3030

3131
from("direct:backend")
32-
.to("file:../client?fileName=output")
32+
.to("file:../client?fileName=output&jailStartingDirectory=false")
3333
.log("done streaming")
3434
.setBody(constant("done"));
3535
}

0 commit comments

Comments
 (0)