This is an automated email from the ASF dual-hosted git repository.
tballison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git
The following commit(s) were added to refs/heads/main by this push:
new 56bf55f7f9 keep gdalinfo from opening files and URLs named in the
document (#3516)
56bf55f7f9 is described below
commit 56bf55f7f997ce344a06666529aa8a1bed63f2b1
Author: Naveed <[email protected]>
AuthorDate: Sat Nov 7 04:03:49 2026 +0530
keep gdalinfo from opening files and URLs named in the document (#3516)
GDAL picks its driver from the file's content, and the VRT and GTI
drivers take any file whose first kilobyte contains <VRTDataset or
<GDALTileIndexDataset. A FITS header followed by a VRT is detected as
application/fits and handed to GDALParser, and gdalinfo then fetches
whatever URL the VRT names. Run gdalinfo with those two drivers skipped
and with no /vsicurl/ name allowed to open.
Generated-by: Claude Code (claude-opus-5-5)
---
.../org/apache/tika/parser/gdal/GDALParser.java | 12 ++++-
.../apache/tika/parser/gdal/TestGDALParser.java | 58 ++++++++++++++++++++++
2 files changed, 69 insertions(+), 1 deletion(-)
diff --git
a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java
b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java
index fb81e7328d..662e0bdfa5 100644
---
a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java
+++
b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java
@@ -201,6 +201,14 @@ public class GDALParser implements Parser {
return args;
}
+ // VRT and GTI open any file whose header merely contains their XML, so a
document of a
+ // type routed here can name other files or URLs for gdalinfo to open.
+ static void restrictEnvironment(Map<String, String> env) {
+ env.merge("GDAL_SKIP", "VRT GTI", (operatorSkip, skip) -> operatorSkip
+ " " + skip);
+ // the input is always a local file, so no /vsicurl/ name needs to open
+ env.put("CPL_VSIL_CURL_ALLOWED_FILENAME", "");
+ }
+
@Override
public Set<MediaType> getSupportedTypes(ParseContext context) {
return SUPPORTED_TYPES;
@@ -220,7 +228,9 @@ public class GDALParser implements Parser {
String[] runCommand = buildCommandLine(this.command,
tis.getFile().getPath());
- FileProcessResult result = ProcessUtils.execute(new
ProcessBuilder(runCommand), context,
+ ProcessBuilder pb = new ProcessBuilder(runCommand);
+ restrictEnvironment(pb.environment());
+ FileProcessResult result = ProcessUtils.execute(pb, context,
timeoutMillis, maxStdOut, maxStdErr);
metadata.set(ExternalProcess.IS_TIMEOUT, result.isTimeout());
diff --git
a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/gdal/TestGDALParser.java
b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/gdal/TestGDALParser.java
index d6e87ac387..ce060f9b3f 100644
---
a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/gdal/TestGDALParser.java
+++
b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/gdal/TestGDALParser.java
@@ -23,6 +23,16 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
import org.junit.jupiter.api.Test;
import org.apache.tika.TikaTest;
@@ -162,4 +172,52 @@ public class TestGDALParser extends TikaTest {
assertArrayEquals(new String[]{"gdalinfo", path},
GDALParser.buildCommandLine(new GDALParser().getCommand(),
path));
}
+
+ @Test
+ public void testDocumentCannotPointGdalinfoAtAUrl() throws Exception {
+ assumeTrue(canRun());
+ try (ServerSocket listener = new ServerSocket(0, 50,
InetAddress.getLoopbackAddress())) {
+ AtomicInteger connections = new AtomicInteger();
+ Thread acceptor = new Thread(() -> {
+ while (true) {
+ try (Socket s = listener.accept()) {
+ connections.incrementAndGet();
+ } catch (IOException e) {
+ return;
+ }
+ }
+ });
+ acceptor.setDaemon(true);
+ acceptor.start();
+
+ String url = "/vsicurl/http://127.0.0.1:" +
listener.getLocalPort() + "/from-document";
+ // a FITS header is what routes the file to GDALParser
+ String fitsHeader = String.format(Locale.ROOT, "%-80s%-80s%n",
+ "SIMPLE = T", "END");
+ String[] documents = {
+ fitsHeader + "<VRTDataset rasterXSize=\"1\"
rasterYSize=\"1\">"
+ + "<VRTRasterBand dataType=\"Byte\"
band=\"1\"><SimpleSource>"
+ + "<SourceFilename relativeToVRT=\"0\">" + url +
"</SourceFilename>"
+ +
"<SourceBand>1</SourceBand></SimpleSource></VRTRasterBand>"
+ + "</VRTDataset>\n",
+ fitsHeader + "<GDALTileIndexDataset><IndexDataset>" + url
+ + "</IndexDataset></GDALTileIndexDataset>\n"};
+ for (String document : documents) {
+ try (TikaInputStream tis = TikaInputStream.get(
+ document.getBytes(StandardCharsets.US_ASCII))) {
+ new GDALParser().parse(tis, new BodyContentHandler(), new
Metadata(),
+ new ParseContext());
+ }
+ }
+ assertEquals(0, connections.get());
+ }
+ }
+
+ @Test
+ public void testOperatorGdalSkipIsKept() {
+ Map<String, String> env = new HashMap<>(Map.of("GDAL_SKIP", "JPEG"));
+ GDALParser.restrictEnvironment(env);
+ assertEquals("JPEG VRT GTI", env.get("GDAL_SKIP"));
+ assertEquals("", env.get("CPL_VSIL_CURL_ALLOWED_FILENAME"));
+ }
}