This is an automated email from the ASF dual-hosted git repository.

gerlowskija pushed a commit to branch branch_10_0
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/branch_10_0 by this push:
     new dbb169a1a07 SOLR-18058: Tweak "allowPath" checks to avoid NPEs
dbb169a1a07 is described below

commit dbb169a1a07c9310df3eaa38c82107e721f2e330
Author: Jason Gerlowski <[email protected]>
AuthorDate: Fri Jan 9 12:22:50 2026 -0500

    SOLR-18058: Tweak "allowPath" checks to avoid NPEs
---
 gradle/libs.versions.toml                                   |  1 -
 solr/core/src/java/org/apache/solr/core/CoreContainer.java  |  8 +++++++-
 .../org/apache/solr/core/FileSystemConfigSetService.java    | 13 +++++++++++++
 solr/core/src/java/org/apache/solr/core/SolrPaths.java      |  4 ++++
 .../apache/solr/response/TestErrorResponseStackTrace.java   |  5 +++++
 .../apache/solr/response/TestPrometheusResponseWriter.java  |  4 ++++
 .../core/src/test/org/apache/solr/search/TestThinCache.java |  7 ++++++-
 .../test/org/apache/solr/servlet/HideStackTraceTest.java    |  5 +++++
 .../client/solrj/jetty/HttpJettySolrClientProxyTest.java    |  6 ++++++
 .../org/apache/solr/util/EmbeddedSolrServerTestRule.java    |  3 +++
 10 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 4a0531410bc..be018993437 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -182,7 +182,6 @@ openjdk-jmh = "1.37"
 opentelemetry = "1.56.0"
 opentelemetry-prometheus = "1.56.0-alpha"
 opentelemetry-runtime-telemetry = "2.22.0-alpha"
-osgi-annotation = "8.1.0"
 oshai-logging = "7.0.13"
 # @keep for version alignment
 ow2-asm = "9.8"
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java 
b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
index 01e40d9f0fb..bb06a189b9f 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -434,6 +434,7 @@ public class CoreContainer {
     SolrPaths.AllowPathBuilder allowPathBuilder = new 
SolrPaths.AllowPathBuilder();
     allowPathBuilder.addPath(cfg.getSolrHome());
     allowPathBuilder.addPath(cfg.getCoreRootDirectory());
+    allowPathBuilder.addPath(cfg.getConfigSetBaseDirectory());
     if (cfg.getSolrDataHome() != null) {
       allowPathBuilder.addPath(cfg.getSolrDataHome());
     }
@@ -1484,6 +1485,10 @@ public class CoreContainer {
         log.warn(msg);
         throw new SolrException(ErrorCode.CONFLICT, msg);
       }
+
+      // Validate 'instancePath' prior to instantiating CoreDescriptor, as CD 
construction attempts
+      // to read properties from 'instancePath'
+      assertPathAllowed(instancePath);
       CoreDescriptor cd =
           new CoreDescriptor(
               coreName, instancePath, parameters, getContainerProperties(), 
getZkController());
@@ -1498,7 +1503,6 @@ public class CoreContainer {
       }
 
       // Validate paths are relative to known locations to avoid path traversal
-      assertPathAllowed(cd.getInstanceDir());
       assertPathAllowed(Path.of(cd.getDataDir()));
 
       boolean preExistingZkEntry = false;
@@ -1570,6 +1574,8 @@ public class CoreContainer {
     }
   }
 
+  public static final String ALLOW_PATHS_SYSPROP = "solr.security.allow.paths";
+
   /**
    * Checks that the given path is relative to SOLR_HOME, SOLR_DATA_HOME, 
coreRootDirectory or one
    * of the paths specified in solr.xml's allowPaths element. Delegates to 
{@link
diff --git 
a/solr/core/src/java/org/apache/solr/core/FileSystemConfigSetService.java 
b/solr/core/src/java/org/apache/solr/core/FileSystemConfigSetService.java
index 1b7cc819fbe..3d31349c066 100644
--- a/solr/core/src/java/org/apache/solr/core/FileSystemConfigSetService.java
+++ b/solr/core/src/java/org/apache/solr/core/FileSystemConfigSetService.java
@@ -56,15 +56,21 @@ public class FileSystemConfigSetService extends 
ConfigSetService {
   public static final String METADATA_FILE = ".metadata.json";
 
   private final Path configSetBase;
+  // TODO currently it's not really possible to check paths against allowPaths 
without a
+  // CoreContainer reference, see SOLR-18059
+  private final CoreContainer cc;
 
   public FileSystemConfigSetService(CoreContainer cc) {
     super(cc.getResourceLoader(), cc.getConfig().hasSchemaCache());
+
+    this.cc = cc;
     this.configSetBase = cc.getConfig().getConfigSetBaseDirectory();
   }
 
   /** Testing purpose */
   protected FileSystemConfigSetService(Path configSetBase) {
     super(null, false);
+    this.cc = null;
     this.configSetBase = configSetBase;
   }
 
@@ -320,6 +326,13 @@ public class FileSystemConfigSetService extends 
ConfigSetService {
     String configSet = cd.getConfigSet();
     if (configSet == null) return cd.getInstanceDir();
     Path configSetDirectory = configSetBase.resolve(configSet);
+
+    // CoreContainer only null in testing scenarios - bit of a hack, but will 
go away with
+    // SOLR-18059
+    if (cc != null) {
+      cc.assertPathAllowed(configSetDirectory);
+    }
+
     if (!Files.isDirectory(configSetDirectory))
       throw new SolrException(
           SolrException.ErrorCode.SERVER_ERROR,
diff --git a/solr/core/src/java/org/apache/solr/core/SolrPaths.java 
b/solr/core/src/java/org/apache/solr/core/SolrPaths.java
index 145f3818698..1855b0fe205 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrPaths.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrPaths.java
@@ -125,6 +125,10 @@ public final class SolrPaths {
      * (not supported as a {@link Path} on Windows), see {@link 
#addPath(String)}.
      */
     public AllowPathBuilder addPath(Path path) {
+      if (path == null) {
+        return this;
+      }
+
       if (paths != ALL_PATHS) {
         if (path.equals(ALL_PATH)) {
           paths = ALL_PATHS;
diff --git 
a/solr/core/src/test/org/apache/solr/response/TestErrorResponseStackTrace.java 
b/solr/core/src/test/org/apache/solr/response/TestErrorResponseStackTrace.java
index ce10d4e2d48..31abab9da58 100644
--- 
a/solr/core/src/test/org/apache/solr/response/TestErrorResponseStackTrace.java
+++ 
b/solr/core/src/test/org/apache/solr/response/TestErrorResponseStackTrace.java
@@ -16,6 +16,8 @@
  */
 package org.apache.solr.response;
 
+import static org.apache.solr.core.CoreContainer.ALLOW_PATHS_SYSPROP;
+
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -30,6 +32,7 @@ import org.apache.solr.client.solrj.apache.HttpClientUtil;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.response.json.JsonMapResponseParser;
 import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.util.EnvUtils;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.handler.component.ResponseBuilder;
 import org.apache.solr.handler.component.SearchComponent;
@@ -47,6 +50,8 @@ public class TestErrorResponseStackTrace extends 
SolrTestCaseJ4 {
   public static void setupSolrHome() throws Exception {
     Path configSet = createTempDir("configSet");
     copyMinConf(configSet);
+    EnvUtils.setProperty(ALLOW_PATHS_SYSPROP, 
configSet.toAbsolutePath().toString());
+
     // insert a special filterCache configuration
     Path solrConfig = configSet.resolve("conf/solrconfig.xml");
     Files.writeString(
diff --git 
a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java 
b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java
index 2c86fc41bfb..34f31d47a5e 100644
--- 
a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java
+++ 
b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java
@@ -17,6 +17,7 @@
 package org.apache.solr.response;
 
 import static 
org.apache.solr.client.solrj.response.InputStreamResponseParser.STREAM_KEY;
+import static org.apache.solr.core.CoreContainer.ALLOW_PATHS_SYSPROP;
 
 import java.io.InputStream;
 import java.lang.invoke.MethodHandles;
@@ -34,6 +35,7 @@ import 
org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.request.GenericSolrRequest;
 import org.apache.solr.client.solrj.response.InputStreamResponseParser;
 import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.util.EnvUtils;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.util.ExternalPaths;
 import org.apache.solr.util.SolrJettyTestRule;
@@ -50,6 +52,8 @@ public class TestPrometheusResponseWriter extends 
SolrTestCaseJ4 {
 
   @BeforeClass
   public static void beforeClass() throws Exception {
+    EnvUtils.setProperty(
+        ALLOW_PATHS_SYSPROP, 
ExternalPaths.SERVER_HOME.toAbsolutePath().toString());
     solrClientTestRule.startSolr(LuceneTestCase.createTempDir());
     solrClientTestRule
         .newCollection("core1")
diff --git a/solr/core/src/test/org/apache/solr/search/TestThinCache.java 
b/solr/core/src/test/org/apache/solr/search/TestThinCache.java
index 55717b7d015..de11569c0bb 100644
--- a/solr/core/src/test/org/apache/solr/search/TestThinCache.java
+++ b/solr/core/src/test/org/apache/solr/search/TestThinCache.java
@@ -16,6 +16,7 @@
  */
 package org.apache.solr.search;
 
+import static org.apache.solr.core.CoreContainer.ALLOW_PATHS_SYSPROP;
 import static org.apache.solr.metrics.SolrMetricProducer.CATEGORY_ATTR;
 import static org.apache.solr.metrics.SolrMetricProducer.NAME_ATTR;
 
@@ -44,6 +45,9 @@ public class TestThinCache extends SolrTestCaseJ4 {
   @ClassRule public static EmbeddedSolrServerTestRule solrRule = new 
EmbeddedSolrServerTestRule();
   public static final String SOLR_NODE_LEVEL_CACHE_XML =
       "<solr>\n"
+          + "  <str name=\"allowPaths\">${"
+          + ALLOW_PATHS_SYSPROP
+          + ":}</str>"
           + "  <caches>\n"
           + "    <cache name='myNodeLevelCache'\n"
           + "      size='10'\n"
@@ -60,11 +64,12 @@ public class TestThinCache extends SolrTestCaseJ4 {
   @BeforeClass
   public static void setupSolrHome() throws Exception {
     Path home = createTempDir("home");
+    Path configSet = createTempDir("configSet");
+    System.setProperty(ALLOW_PATHS_SYSPROP, 
configSet.toAbsolutePath().toString());
     Files.writeString(home.resolve("solr.xml"), SOLR_NODE_LEVEL_CACHE_XML);
 
     solrRule.startSolr(home);
 
-    Path configSet = createTempDir("configSet");
     copyMinConf(configSet);
     // insert a special filterCache configuration
     Path solrConfig = configSet.resolve("conf/solrconfig.xml");
diff --git a/solr/core/src/test/org/apache/solr/servlet/HideStackTraceTest.java 
b/solr/core/src/test/org/apache/solr/servlet/HideStackTraceTest.java
index db58af874c2..03a1b06a933 100644
--- a/solr/core/src/test/org/apache/solr/servlet/HideStackTraceTest.java
+++ b/solr/core/src/test/org/apache/solr/servlet/HideStackTraceTest.java
@@ -16,6 +16,8 @@
  */
 package org.apache.solr.servlet;
 
+import static org.apache.solr.core.CoreContainer.ALLOW_PATHS_SYSPROP;
+
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -26,6 +28,7 @@ import org.apache.lucene.tests.util.LuceneTestCase;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
 import org.apache.solr.client.solrj.apache.HttpClientUtil;
+import org.apache.solr.common.util.EnvUtils;
 import org.apache.solr.handler.component.ResponseBuilder;
 import org.apache.solr.handler.component.SearchComponent;
 import org.apache.solr.util.SolrJettyTestRule;
@@ -47,6 +50,8 @@ public class HideStackTraceTest extends SolrTestCaseJ4 {
 
     Path configSet = createTempDir("configSet");
     copyMinConf(configSet);
+    EnvUtils.setProperty(ALLOW_PATHS_SYSPROP, 
configSet.toAbsolutePath().toString());
+
     // insert a special filterCache configuration
     Path solrConfig = configSet.resolve("conf/solrconfig.xml");
     Files.writeString(
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/jetty/HttpJettySolrClientProxyTest.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/jetty/HttpJettySolrClientProxyTest.java
index ec887fe4f26..83864ba6d91 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/jetty/HttpJettySolrClientProxyTest.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/jetty/HttpJettySolrClientProxyTest.java
@@ -16,6 +16,8 @@
  */
 package org.apache.solr.client.solrj.jetty;
 
+import static org.apache.solr.core.CoreContainer.ALLOW_PATHS_SYSPROP;
+
 import com.carrotsearch.randomizedtesting.RandomizedTest;
 import java.util.Arrays;
 import java.util.Objects;
@@ -27,6 +29,7 @@ import org.apache.solr.client.solrj.impl.HttpJdkSolrClient;
 import org.apache.solr.client.solrj.impl.HttpSolrClientBase;
 import org.apache.solr.client.solrj.request.SolrQuery;
 import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.common.util.EnvUtils;
 import org.apache.solr.embedded.JettyConfig;
 import org.apache.solr.util.ExternalPaths;
 import org.apache.solr.util.SocketProxy;
@@ -46,6 +49,9 @@ public class HttpJettySolrClientProxyTest extends 
SolrTestCaseJ4 {
   public static void beforeTest() throws Exception {
     RandomizedTest.assumeFalse(sslConfig.isSSLMode());
 
+    EnvUtils.setProperty(
+        ALLOW_PATHS_SYSPROP,
+        ExternalPaths.SERVER_HOME.toAbsolutePath().toString()); // Needed for 
configset location
     solrClientTestRule.enableProxy();
     solrClientTestRule.startSolr(createTempDir(), new Properties(), 
JettyConfig.builder().build());
     // Actually only need extremely minimal configSet but just use the default
diff --git 
a/solr/test-framework/src/java/org/apache/solr/util/EmbeddedSolrServerTestRule.java
 
b/solr/test-framework/src/java/org/apache/solr/util/EmbeddedSolrServerTestRule.java
index b7c1e3d003c..1d4cd23b9a5 100644
--- 
a/solr/test-framework/src/java/org/apache/solr/util/EmbeddedSolrServerTestRule.java
+++ 
b/solr/test-framework/src/java/org/apache/solr/util/EmbeddedSolrServerTestRule.java
@@ -19,10 +19,12 @@ package org.apache.solr.util;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Properties;
+import java.util.Set;
 import org.apache.lucene.tests.util.LuceneTestCase;
 import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.core.NodeConfig;
+import org.apache.solr.core.SolrPaths;
 import org.apache.solr.core.SolrXmlConfig;
 import org.apache.solr.update.UpdateShardHandlerConfig;
 
@@ -87,6 +89,7 @@ public class EmbeddedSolrServerTestRule extends 
SolrClientTestRule {
 
     return new NodeConfig.NodeConfigBuilder("testNode", solrHome)
         .setUpdateShardHandlerConfig(UpdateShardHandlerConfig.TEST_DEFAULT)
+        .setAllowPaths(Set.of(SolrPaths.ALL_PATH))
         
.setCoreRootDirectory(LuceneTestCase.createTempDir("cores").toString());
   }
 

Reply via email to