oscerd commented on code in PR #27119:
URL: https://github.com/apache/camel/pull/27119#discussion_r4165198373


##########
components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageConsumer.java:
##########
@@ -360,13 +360,30 @@ protected String evaluateFileExpression(Exchange 
exchange, String downloadFileNa
         // use blob as file name
         exchange.getMessage().setHeader(GoogleCloudStorageConstants.FILE_NAME, 
blogName);
 
+        // the local path is resolved from 
GoogleCloudStorageConstants.FILE_NAME set above, which carries the remote
+        // object name and is therefore untrusted input, no matter whether the 
token is appended here or already part
+        // of the configured downloadFileName. An absolute object name, or one 
with a .. segment, is rejected whatever
+        // the configuration looks like, and the resolved path is then 
confined:
+        // - plain directory (no expression): the object name is appended to 
it and the configured value itself is the
+        //   directory the download must stay within
+        // - directory followed by an expression (for example 
/tmp/downloads/${file:name}): the static directory
+        //   prefix before the first expression token is the directory the 
download must stay within
+        // - fully dynamic value with no static directory prefix (for example 
${file:name}): the route author did not
+        //   configure any directory, so a relative result must stay within 
the working directory
+        if (blogName != null) {
+            GoogleCloudStorageFileNameHelper.assertSafeObjectName(blogName);
+        }

Review Comment:
   You're right, and the failed poll was the bigger problem: one object with 
such a name stopped the rest of the bucket from being consumed, which is a lot 
more than "objects with such names change behaviour".
   
   I went with your second option, in `99486e0a4298`. The strict name check 
stays, since rejecting absolute and `..` names whatever the template looks like 
is the intended behaviour (and is what the upgrade guide describes). What 
changed is that a rejected object is now handled on its own: 
`createExchanges(List<Blob>)` reports it through 
`getExceptionHandler().handleException(...)` and skips it, so the other objects 
of the poll are consumed as usual. The exchange already created for the 
rejected object is released rather than left behind.
   
   Your example is now a test 
(`objectWithARejectedNameIsSkippedWithoutStoppingTheOthers`): with 
`downloadFileName=<dir>/${exchangeId}.bin` and objects `a.txt`, `b/../c.txt` 
and `d.txt`, the exchanges for `a.txt` and `d.txt` are created and `b/../c.txt` 
is reported once. The upgrade guide now also says what happens to such an 
object: it is skipped and reported on every poll until it is removed or renamed.
   
   On `hasDriveLetter`: intended. The check is deliberately the same on every 
OS, so a bucket consumed from Windows and Linux deployments behaves the same, 
and `C:report.txt` is rejected on Linux as well, as the upgrade guide says.
   
   _Claude Code on behalf of oscerd_



-- 
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