VYPR
Low severityNVD Advisory· Published Feb 9, 2024· Updated May 15, 2025

Apache Solr: Solr Schema Designer blindly "trusts" all configsets, possibly leading to RCE by unauthenticated users

CVE-2023-50292

Description

Incorrect Permission Assignment for Critical Resource, Improper Control of Dynamically-Managed Code Resources vulnerability in Apache Solr.

This issue affects Apache Solr: from 8.10.0 through 8.11.2, from 9.0.0 before 9.3.0.

The Schema Designer was introduced to allow users to more easily configure and test new Schemas and configSets. However, when the feature was created, the "trust" (authentication) of these configSets was not considered. External library loading is only available to configSets that are "trusted" (created by authenticated users), thus non-authenticated users are unable to perform Remote Code Execution. Since the Schema Designer loaded configSets without taking their "trust" into account, configSets that were created by unauthenticated users were allowed to load external libraries when used in the Schema Designer.

Users are recommended to upgrade to version 9.3.0, which fixes the issue.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

In Apache Solr, the Schema Designer fails to check configSet trust, allowing unauthenticated users to load external libraries and achieve remote code execution.

Root

Cause CVE-2023-50292 is an improper permission assignment and dynamic code resource vulnerability in Apache Solr's Schema Designer. The issue affects Solr versions from 8.10.0 through 8.11.2 and 9.0.0 before 9.3.0 [2]. The Schema Designer was introduced to simplify schema and configSet configuration, but it did not check whether a configSet was "trusted" (i.e., created by an authenticated user) before loading it. This oversight allowed configSets created by unauthenticated users to be used in the Schema Designer [1][2].

Exploitation

External library loading is normally restricted to trusted configSets, which are only created by authenticated users; this prevents unauthenticated Remote Code Execution (RCE) [2]. Because the Schema Designer bypassed the trust check, an unauthenticated attacker could submit a malicious configSet that includes an external library reference. When the Schema Designer loads that configSet, Solr loads the external library, enabling code execution [4]. No additional authentication is required, as the Schema Designer is accessible to unauthenticated users by default.

Impact

Successful exploitation allows an unauthenticated attacker to achieve RCE on the Solr server, compromising the confidentiality, integrity, and availability of the system [2].

Mitigation

Users are strongly recommended to upgrade to Solr version 9.3.0, which fixes the issue by properly managing configSet trust in the Schema Designer [1][2][3]. The commit d07751c updates the ZkConfigSetService to check trust before loading configSets in the designer [3]. No workaround is provided for earlier versions; upgrading is the only fully effective measure.

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.apache.solr:solr-coreMaven
>= 9.0.0, < 9.3.09.3.0
org.apache.solr:solr-coreMaven
>= 8.10.0, < 8.11.38.11.3

Affected products

3

Patches

2
6e9ed203b309

SOLR-16777: Schema Designer now correctly manages trust of the ConfigSets it is managing

https://github.com/apache/lucene-solrIshan ChattopadhyayaNov 3, 2023via ghsa
6 files changed · +87 21
  • solr/CHANGES.txt+2 0 modified
    @@ -37,6 +37,8 @@ Bug Fixes
     
     * SOLR-16452: Do not update PRS states if local version is newer (Hitesh Khamesra via noble)
     
    +* SOLR-16777: Schema Designer now correctly manages trust of the ConfigSets it is managing. (Ishan Chattopadhyaya, Skay, Houston Putman)
    +
     Optimizations
     ---------------------
     * SOLR-16555: SolrIndexSearcher - FilterCache intersections/andNot should not clone bitsets repeatedly (Kevin Risden, David Smiley)
    
  • solr/core/src/java/org/apache/solr/handler/admin/ConfigSetsHandler.java+29 2 modified
    @@ -16,6 +16,7 @@
      */
     package org.apache.solr.handler.admin;
     
    +import java.io.IOException;
     import java.io.InputStream;
     import java.lang.invoke.MethodHandles;
     import java.nio.charset.StandardCharsets;
    @@ -311,7 +312,7 @@ private void ensureOverwritingUntrustedConfigSet(SolrZkClient zkClient, String c
         }
       }
     
    -  private static boolean isCurrentlyTrusted(SolrZkClient zkClient, String configSetZkPath) {
    +  public static boolean isCurrentlyTrusted(SolrZkClient zkClient, String configSetZkPath) {
         byte[] configSetNodeContent;
         try {
           configSetNodeContent = zkClient.getData(configSetZkPath, null, null, true);
    @@ -329,7 +330,33 @@ private static boolean isCurrentlyTrusted(SolrZkClient zkClient, String configSe
         return (boolean) contentMap.getOrDefault("trusted", true);
       }
     
    -  static boolean isTrusted(SolrQueryRequest req, AuthenticationPlugin authPlugin) {
    +  public void setConfigMetadata(String configName, Map<String, Object> data) throws IOException {
    +    try {
    +      coreContainer.getZkController().getZkClient().makePath(
    +          ZkConfigManager.CONFIGS_ZKNODE + "/" + configName,
    +          Utils.toJSON(data),
    +          CreateMode.PERSISTENT,
    +          null,
    +          false,
    +          true);
    +    } catch (KeeperException | InterruptedException e) {
    +      throw new IOException("Error setting config metadata", SolrZkClient.checkInterrupted(e));
    +    }
    +  }
    +
    +  public void removeConfigSetTrust(String configSetName) {
    +    try {
    +      Map<String, Object> metadata = Collections.singletonMap("trusted", false);
    +      setConfigMetadata(configSetName, metadata);
    +    } catch (IOException e) {
    +      throw new SolrException(
    +          SolrException.ErrorCode.SERVER_ERROR,
    +          "Could not remove trusted flag for configSet " + configSetName + ": " + e.getMessage(),
    +          e);
    +    }
    +  }
    +
    +  public static boolean isTrusted(SolrQueryRequest req, AuthenticationPlugin authPlugin) {
         if (authPlugin != null && req.getUserPrincipal() != null) {
           log.debug("Trusted configset request");
           return true;
    
  • solr/core/src/java/org/apache/solr/handler/designer/SchemaDesignerAPI.java+9 2 modified
    @@ -65,6 +65,7 @@
     import org.apache.solr.core.CoreContainer;
     import org.apache.solr.core.SolrConfig;
     import org.apache.solr.core.SolrResourceLoader;
    +import org.apache.solr.handler.admin.ConfigSetsHandler;
     import org.apache.solr.request.SolrQueryRequest;
     import org.apache.solr.response.RawResponseWriter;
     import org.apache.solr.response.SolrQueryResponse;
    @@ -112,8 +113,8 @@ public SchemaDesignerAPI(CoreContainer coreContainer) {
         this.coreContainer = coreContainer;
         this.schemaSuggester = schemaSuggester;
         this.sampleDocLoader = sampleDocLoader;
    -    this.settingsDAO = new SchemaDesignerSettingsDAO(coreContainer);
         this.configSetHelper = new SchemaDesignerConfigSetHelper(this.coreContainer, this.schemaSuggester);
    +    this.settingsDAO = new SchemaDesignerSettingsDAO(coreContainer, configSetHelper);
       }
     
       public static SchemaSuggester newSchemaSuggester(CoreContainer coreContainer) {
    @@ -233,11 +234,12 @@ public void updateFileContents(SolrQueryRequest req, SolrQueryResponse rsp) thro
     
         byte[] data = DefaultSampleDocumentsLoader.streamAsBytes(extractSingleContentStream(req, true).getStream());
         Exception updateFileError = null;
    +    boolean requestIsTrusted = ConfigSetsHandler.isTrusted(req, coreContainer.getAuthenticationPlugin());
         if (SOLR_CONFIG_XML.equals(file)) {
           // verify the updated solrconfig.xml is valid before saving to ZK (to avoid things blowing up later)
           try {
             InMemoryResourceLoader loader = new InMemoryResourceLoader(coreContainer, mutableId, SOLR_CONFIG_XML, data);
    -        SolrConfig.readFromResourceLoader(loader, SOLR_CONFIG_XML, true, null);
    +        SolrConfig.readFromResourceLoader(loader, SOLR_CONFIG_XML, requestIsTrusted, null);
           } catch (Exception exc) {
             updateFileError = exc;
           }
    @@ -260,6 +262,11 @@ public void updateFileContents(SolrQueryRequest req, SolrQueryResponse rsp) thro
         } catch (KeeperException | InterruptedException e) {
           throw new IOException("Failed to save data in ZK at path: " + zkPath, SolrZkClient.checkInterrupted(e));
         }
    +    // If the request is untrusted, and the configSet is trusted, remove the trusted flag on the
    +    // configSet.
    +    if (ConfigSetsHandler.isCurrentlyTrusted(zkClient, ZkConfigManager.CONFIGS_ZKNODE + "/" + mutableId) && !requestIsTrusted) {
    +      coreContainer.getConfigSetsHandler().removeConfigSetTrust(mutableId);
    +    }
     
         configSetHelper.reloadTempCollection(mutableId, false);
     
    
  • solr/core/src/java/org/apache/solr/handler/designer/SchemaDesignerConfigSetHelper.java+33 4 modified
    @@ -610,10 +610,9 @@ ManagedIndexSchema deleteNestedDocsFieldsIfNeeded(ManagedIndexSchema schema, boo
       }
     
       SolrConfig loadSolrConfig(String configSet) {
    -    SolrResourceLoader resourceLoader = cc.getResourceLoader();
    -    ZkSolrResourceLoader zkLoader =
    -        new ZkSolrResourceLoader(resourceLoader.getInstancePath(), configSet, resourceLoader.getClassLoader(), new Properties(), cc.getZkController());
    -    return SolrConfig.readFromResourceLoader(zkLoader, SOLR_CONFIG_XML, false, null);
    +    ZkSolrResourceLoader zkLoader = zkLoaderForConfigSet(configSet);
    +    boolean trusted = isConfigSetTrusted(configSet);
    +    return SolrConfig.readFromResourceLoader(zkLoader, SOLR_CONFIG_XML, trusted, null);
       }
     
       ManagedIndexSchema loadLatestSchema(String configSet) {
    @@ -1075,4 +1074,34 @@ void deleteConfig(String configSet) throws IOException {
       void copyConfig(String from, String to) throws IOException {
         configManager.copyConfigDir(from, to);
       }
    +
    +  public boolean isConfigSetTrusted(String configSetName) {
    +    try {
    +      return cc.getConfigSetsHandler().isCurrentlyTrusted(cc.getZkController().getZkClient(), ZkConfigManager.CONFIGS_ZKNODE + "/" + configSetName);
    +    } catch (Exception e) {
    +      throw new SolrException(
    +          SolrException.ErrorCode.SERVER_ERROR,
    +          "Could not load conf " + configSetName + ": " + e.getMessage(),
    +          e);
    +    }
    +  }
    +
    +  public void removeConfigSetTrust(String configSetName) {
    +    try {
    +      Map<String, Object> metadata = Collections.singletonMap("trusted", false);
    +      cc.getConfigSetsHandler().setConfigMetadata(configSetName, metadata);
    +    } catch (IOException e) {
    +      throw new SolrException(
    +          SolrException.ErrorCode.SERVER_ERROR,
    +          "Could not remove trusted flag for configSet " + configSetName + ": " + e.getMessage(),
    +          e);
    +    }
    +  }
    +
    +  protected ZkSolrResourceLoader zkLoaderForConfigSet(final String configSet) {
    +    SolrResourceLoader resourceLoader = cc.getResourceLoader();
    +    ZkSolrResourceLoader zkLoader =
    +        new ZkSolrResourceLoader(resourceLoader.getInstancePath(), configSet, resourceLoader.getClassLoader(), new Properties(), cc.getZkController());
    +    return zkLoader;
    +  }
     }
    
  • solr/core/src/java/org/apache/solr/handler/designer/SchemaDesignerSettingsDAO.java+12 12 modified
    @@ -24,7 +24,6 @@
     import java.util.HashMap;
     import java.util.List;
     import java.util.Map;
    -import java.util.Properties;
     
     import org.apache.solr.cloud.ZkController;
     import org.apache.solr.cloud.ZkSolrResourceLoader;
    @@ -33,7 +32,6 @@
     import org.apache.solr.core.CoreContainer;
     import org.apache.solr.core.PluginInfo;
     import org.apache.solr.core.SolrConfig;
    -import org.apache.solr.core.SolrResourceLoader;
     import org.apache.solr.update.processor.UpdateRequestProcessorChain;
     import org.apache.zookeeper.KeeperException;
     import org.apache.zookeeper.data.Stat;
    @@ -49,14 +47,15 @@ class SchemaDesignerSettingsDAO implements SchemaDesignerConstants {
       private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
     
       private final CoreContainer cc;
    +  private final SchemaDesignerConfigSetHelper configSetHelper;
     
    -  SchemaDesignerSettingsDAO(CoreContainer cc) {
    +  SchemaDesignerSettingsDAO(CoreContainer cc, SchemaDesignerConfigSetHelper configSetHelper) {
         this.cc = cc;
    +    this.configSetHelper = configSetHelper;
       }
     
       SchemaDesignerSettings getSettings(String configSet) {
    -    SolrConfig solrConfig =
    -        SolrConfig.readFromResourceLoader(zkLoaderForConfigSet(configSet), SOLR_CONFIG_XML, true, null);
    +    SolrConfig solrConfig = configSetHelper.loadSolrConfig(configSet);
         return getSettings(solrConfig);
       }
     
    @@ -97,8 +96,14 @@ boolean persistIfChanged(String configSet, SchemaDesignerSettings settings) thro
         }
     
         if (changed) {
    -      ZkController.persistConfigResourceToZooKeeper(zkLoaderForConfigSet(configSet), overlay.getZnodeVersion(),
    -          ConfigOverlay.RESOURCE_NAME, overlay.toByteArray(), true);
    +      try (ZkSolrResourceLoader resourceLoader = configSetHelper.zkLoaderForConfigSet(configSet)) {
    +        ZkController.persistConfigResourceToZooKeeper(
    +            resourceLoader,
    +            overlay.getZnodeVersion(),
    +            ConfigOverlay.RESOURCE_NAME,
    +            overlay.toByteArray(),
    +            true);
    +      }
         }
     
         return changed;
    @@ -160,9 +165,4 @@ private boolean hasFieldGuessingURPChain(final SolrConfig solrConfig) {
         }
         return hasPlugin;
       }
    -
    -  private ZkSolrResourceLoader zkLoaderForConfigSet(final String configSet) {
    -    SolrResourceLoader loader = cc.getResourceLoader();
    -    return new ZkSolrResourceLoader(loader.getInstancePath(), configSet, loader.getClassLoader(), new Properties(), cc.getZkController());
    -  }
     }
    
  • solr/core/src/test/org/apache/solr/handler/designer/TestSchemaDesignerSettingsDAO.java+2 1 modified
    @@ -69,7 +69,8 @@ public void testDAO() throws Exception {
             CollectionAdminRequest.createCollection(collection, configSet, 1, 1).process(cluster.getSolrClient());
         CollectionsHandler.waitForActiveCollection(collection, cc, rsp);
     
    -    SchemaDesignerSettingsDAO dao = new SchemaDesignerSettingsDAO(cc);
    +    SchemaDesignerConfigSetHelper csh = new SchemaDesignerConfigSetHelper(cc, null);
    +    SchemaDesignerSettingsDAO dao = new SchemaDesignerSettingsDAO(cc, csh);
         SchemaDesignerSettings settings = dao.getSettings(configSet);
         assertNotNull(settings);
     
    
d07751cfaa80

SOLR-16777: Make SchemaDesigner use ConfigSet trust

https://github.com/apache/solrHouston PutmanJul 10, 2023via ghsa
12 files changed · +111 54
  • solr/CHANGES.txt+1 1 modified
    @@ -229,7 +229,7 @@ Bug Fixes
     
     * SOLR-13605: Fix setting client scoped socket and connect timeouts when using HttpSolrClient.Builder.withHttpClient() method.  (Eric Pugh, Alex Deparvu)
     
    -* SOLR-16777: Fix for Schema Designer blindly trusting potentially malicious configsets (Ishan Chattopadhyaya, Skay)
    +* SOLR-16777: Schema Designer now correctly manages trust of the ConfigSets it is managing. (Ishan Chattopadhyaya, Skay, Houston Putman)
     
     * SOLR-16771: Fixed behavior and handling of 'unset' logging levels in /admin/info/logging API and related Admin UI (hossman)
     
    
  • solr/core/src/java/org/apache/solr/cloud/ZkConfigSetService.java+2 2 modified
    @@ -101,9 +101,9 @@ public SolrResourceLoader createCoreResourceLoader(CoreDescriptor cd) {
       }
     
       @Override
    -  protected NamedList<Object> loadConfigSetFlags(CoreDescriptor cd, SolrResourceLoader loader)
    -      throws IOException {
    +  protected NamedList<Object> loadConfigSetFlags(SolrResourceLoader loader) throws IOException {
         try {
    +      // ConfigSet flags are loaded from the metadata of the ZK node of the configset.
           return ConfigSetProperties.readFromResourceLoader(loader, ".");
         } catch (Exception ex) {
           log.debug("No configSet flags", ex);
    
  • solr/core/src/java/org/apache/solr/core/ConfigSetService.java+28 14 modified
    @@ -29,7 +29,6 @@
     import java.util.regex.Pattern;
     import org.apache.solr.cloud.ZkConfigSetService;
     import org.apache.solr.cloud.ZkController;
    -import org.apache.solr.cloud.ZkSolrResourceLoader;
     import org.apache.solr.common.ConfigNode;
     import org.apache.solr.common.SolrException;
     import org.apache.solr.common.util.NamedList;
    @@ -220,6 +219,31 @@ public static void bootstrapConf(CoreContainer cc) throws IOException {
         }
       }
     
    +  /**
    +   * Return whether the given configSet is trusted.
    +   *
    +   * @param name name of the configSet
    +   */
    +  public boolean isConfigSetTrusted(String name) throws IOException {
    +    Map<String, Object> contentMap = getConfigMetadata(name);
    +    return (boolean) contentMap.getOrDefault("trusted", true);
    +  }
    +
    +  /**
    +   * Return whether the configSet used for the given resourceLoader is trusted.
    +   *
    +   * @param coreLoader resourceLoader for a core
    +   */
    +  public boolean isConfigSetTrusted(SolrResourceLoader coreLoader) throws IOException {
    +    // ConfigSet flags are loaded from the metadata of the ZK node of the configset. (For the
    +    // ZKConfigSetService)
    +    NamedList<?> flags = loadConfigSetFlags(coreLoader);
    +
    +    // Trust if there is no trusted flag (i.e. the ConfigSetApi was not used for this configSet)
    +    // or if the trusted flag is set to "true".
    +    return (flags == null || flags.get("trusted") == null || flags.getBooleanArg("trusted"));
    +  }
    +
       /**
        * Load the ConfigSet for a core
        *
    @@ -233,16 +257,7 @@ public final ConfigSet loadConfigSet(CoreDescriptor dcore) {
         try {
           // ConfigSet properties are loaded from ConfigSetProperties.DEFAULT_FILENAME file.
           NamedList<?> properties = loadConfigSetProperties(dcore, coreLoader);
    -      // ConfigSet flags are loaded from the metadata of the ZK node of the configset.
    -      NamedList<?> flags = loadConfigSetFlags(dcore, coreLoader);
    -
    -      boolean trusted =
    -          (coreLoader instanceof ZkSolrResourceLoader
    -                  && flags != null
    -                  && flags.get("trusted") != null
    -                  && !flags.getBooleanArg("trusted"))
    -              ? false
    -              : true;
    +      boolean trusted = isConfigSetTrusted(coreLoader);
     
           SolrConfig solrConfig = createSolrConfig(dcore, coreLoader, trusted);
           return new ConfigSet(
    @@ -290,7 +305,7 @@ public ConfigSetService(SolrResourceLoader loader, boolean shareSchema) {
        * @return a SolrConfig object
        */
       protected SolrConfig createSolrConfig(
    -      CoreDescriptor cd, SolrResourceLoader loader, boolean isTrusted) {
    +      CoreDescriptor cd, SolrResourceLoader loader, boolean isTrusted) throws IOException {
         return SolrConfig.readFromResourceLoader(
             loader, cd.getConfigName(), isTrusted, cd.getSubstitutableProperties());
       }
    @@ -364,8 +379,7 @@ protected NamedList<Object> loadConfigSetProperties(CoreDescriptor cd, SolrResou
     
       /** Return the ConfigSet flags or null if none. */
       // TODO should fold into configSetProps -- SOLR-14059
    -  protected NamedList<Object> loadConfigSetFlags(CoreDescriptor cd, SolrResourceLoader loader)
    -      throws IOException {
    +  protected NamedList<Object> loadConfigSetFlags(SolrResourceLoader loader) throws IOException {
         return null;
       }
     
    
  • solr/core/src/java/org/apache/solr/handler/configsets/ConfigSetAPIBase.java+2 7 modified
    @@ -109,7 +109,7 @@ protected InputStream ensureNonEmptyInputStream(SolrQueryRequest req) throws IOE
         return contentStreamsIterator.next().getStream();
       }
     
    -  protected boolean isTrusted(Principal userPrincipal, AuthenticationPlugin authPlugin) {
    +  public static boolean isTrusted(Principal userPrincipal, AuthenticationPlugin authPlugin) {
         if (authPlugin != null && userPrincipal != null) {
           log.debug("Trusted configset request");
           return true;
    @@ -118,11 +118,6 @@ protected boolean isTrusted(Principal userPrincipal, AuthenticationPlugin authPl
         return false;
       }
     
    -  protected boolean isCurrentlyTrusted(String configName) throws IOException {
    -    Map<String, Object> contentMap = configSetService.getConfigMetadata(configName);
    -    return (boolean) contentMap.getOrDefault("trusted", true);
    -  }
    -
       protected void createBaseNode(
           ConfigSetService configSetService,
           boolean overwritesExisting,
    @@ -146,7 +141,7 @@ protected void createBaseNode(
        * Fail if an untrusted request tries to update a trusted ConfigSet
        */
       private void ensureOverwritingUntrustedConfigSet(String configName) throws IOException {
    -    boolean isCurrentlyTrusted = isCurrentlyTrusted(configName);
    +    boolean isCurrentlyTrusted = configSetService.isConfigSetTrusted(configName);
         if (isCurrentlyTrusted) {
           throw new SolrException(
               SolrException.ErrorCode.BAD_REQUEST,
    
  • solr/core/src/java/org/apache/solr/handler/configsets/CreateConfigSetAPI.java+1 1 modified
    @@ -64,7 +64,7 @@ public void create(PayloadObj<CreateConfigPayload> obj) throws Exception {
     
         if (!DISABLE_CREATE_AUTH_CHECKS
             && !isTrusted(obj.getRequest().getUserPrincipal(), coreContainer.getAuthenticationPlugin())
    -        && isCurrentlyTrusted(createConfigPayload.baseConfigSet)) {
    +        && configSetService.isConfigSetTrusted(createConfigPayload.baseConfigSet)) {
           throw new SolrException(
               SolrException.ErrorCode.UNAUTHORIZED,
               "Can't create a configset with an unauthenticated request from a trusted "
    
  • solr/core/src/java/org/apache/solr/handler/configsets/UploadConfigSetAPI.java+4 1 modified
    @@ -106,7 +106,10 @@ public void uploadConfigSet(SolrQueryRequest req, SolrQueryResponse rsp) throws
     
         // If the request is doing a full trusted overwrite of an untrusted configSet (overwrite=true,
         // cleanup=true), then trust the configSet.
    -    if (cleanup && requestIsTrusted && overwritesExisting && !isCurrentlyTrusted(configSetName)) {
    +    if (cleanup
    +        && requestIsTrusted
    +        && overwritesExisting
    +        && !configSetService.isConfigSetTrusted(configSetName)) {
           Map<String, Object> metadata = Collections.singletonMap("trusted", true);
           configSetService.setConfigMetadata(configSetName, metadata);
         }
    
  • solr/core/src/java/org/apache/solr/handler/designer/SchemaDesignerAPI.java+10 2 modified
    @@ -72,6 +72,7 @@
     import org.apache.solr.core.CoreContainer;
     import org.apache.solr.core.SolrConfig;
     import org.apache.solr.core.SolrResourceLoader;
    +import org.apache.solr.handler.configsets.ConfigSetAPIBase;
     import org.apache.solr.request.SolrQueryRequest;
     import org.apache.solr.response.RawResponseWriter;
     import org.apache.solr.response.SolrQueryResponse;
    @@ -113,9 +114,9 @@ public SchemaDesignerAPI(CoreContainer coreContainer) {
         this.coreContainer = coreContainer;
         this.schemaSuggester = schemaSuggester;
         this.sampleDocLoader = sampleDocLoader;
    -    this.settingsDAO = new SchemaDesignerSettingsDAO(coreContainer);
         this.configSetHelper =
             new SchemaDesignerConfigSetHelper(this.coreContainer, this.schemaSuggester);
    +    this.settingsDAO = new SchemaDesignerSettingsDAO(coreContainer, configSetHelper);
       }
     
       public static SchemaSuggester newSchemaSuggester(CoreContainer coreContainer) {
    @@ -244,13 +245,15 @@ public void updateFileContents(SolrQueryRequest req, SolrQueryResponse rsp)
             DefaultSampleDocumentsLoader.streamAsBytes(
                 extractSingleContentStream(req, true).getStream());
         Exception updateFileError = null;
    +    boolean requestIsTrusted =
    +        ConfigSetAPIBase.isTrusted(req.getUserPrincipal(), coreContainer.getAuthenticationPlugin());
         if (SOLR_CONFIG_XML.equals(file)) {
           // verify the updated solrconfig.xml is valid before saving to ZK (to avoid things blowing up
           // later)
           try {
             InMemoryResourceLoader loader =
                 new InMemoryResourceLoader(coreContainer, mutableId, SOLR_CONFIG_XML, data);
    -        SolrConfig.readFromResourceLoader(loader, SOLR_CONFIG_XML, true, null);
    +        SolrConfig.readFromResourceLoader(loader, SOLR_CONFIG_XML, requestIsTrusted, null);
           } catch (Exception exc) {
             updateFileError = exc;
           }
    @@ -275,6 +278,11 @@ public void updateFileContents(SolrQueryRequest req, SolrQueryResponse rsp)
           throw new IOException(
               "Failed to save data in ZK at path: " + zkPath, SolrZkClient.checkInterrupted(e));
         }
    +    // If the request is untrusted, and the configSet is trusted, remove the trusted flag on the
    +    // configSet.
    +    if (configSetHelper.isConfigSetTrusted(mutableId) && !requestIsTrusted) {
    +      configSetHelper.removeConfigSetTrust(mutableId);
    +    }
     
         configSetHelper.reloadTempCollection(mutableId, false);
     
    
  • solr/core/src/java/org/apache/solr/handler/designer/SchemaDesignerConfigSetHelper.java+33 8 modified
    @@ -685,14 +685,10 @@ ManagedIndexSchema deleteNestedDocsFieldsIfNeeded(ManagedIndexSchema schema, boo
       }
     
       SolrConfig loadSolrConfig(String configSet) {
    -    SolrResourceLoader resourceLoader = cc.getResourceLoader();
    -    ZkSolrResourceLoader zkLoader =
    -        new ZkSolrResourceLoader(
    -            resourceLoader.getInstancePath(),
    -            configSet,
    -            resourceLoader.getClassLoader(),
    -            cc.getZkController());
    -    return SolrConfig.readFromResourceLoader(zkLoader, SOLR_CONFIG_XML, false, null);
    +    ZkSolrResourceLoader zkLoader = zkLoaderForConfigSet(configSet);
    +    boolean trusted = isConfigSetTrusted(configSet);
    +
    +    return SolrConfig.readFromResourceLoader(zkLoader, SOLR_CONFIG_XML, trusted, null);
       }
     
       ManagedIndexSchema loadLatestSchema(String configSet) {
    @@ -1221,4 +1217,33 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
         }
         return baos.toByteArray();
       }
    +
    +  public boolean isConfigSetTrusted(String configSetName) {
    +    try {
    +      return cc.getConfigSetService().isConfigSetTrusted(configSetName);
    +    } catch (IOException e) {
    +      throw new SolrException(
    +          SolrException.ErrorCode.SERVER_ERROR,
    +          "Could not load conf " + configSetName + ": " + e.getMessage(),
    +          e);
    +    }
    +  }
    +
    +  public void removeConfigSetTrust(String configSetName) {
    +    try {
    +      Map<String, Object> metadata = Collections.singletonMap("trusted", false);
    +      cc.getConfigSetService().setConfigMetadata(configSetName, metadata);
    +    } catch (IOException e) {
    +      throw new SolrException(
    +          SolrException.ErrorCode.SERVER_ERROR,
    +          "Could not remove trusted flag for configSet " + configSetName + ": " + e.getMessage(),
    +          e);
    +    }
    +  }
    +
    +  protected ZkSolrResourceLoader zkLoaderForConfigSet(final String configSet) {
    +    SolrResourceLoader loader = cc.getResourceLoader();
    +    return new ZkSolrResourceLoader(
    +        loader.getInstancePath(), configSet, loader.getClassLoader(), cc.getZkController());
    +  }
     }
    
  • solr/core/src/java/org/apache/solr/handler/designer/SchemaDesignerSettingsDAO.java+12 17 modified
    @@ -33,7 +33,6 @@
     import org.apache.solr.core.CoreContainer;
     import org.apache.solr.core.PluginInfo;
     import org.apache.solr.core.SolrConfig;
    -import org.apache.solr.core.SolrResourceLoader;
     import org.apache.solr.update.processor.UpdateRequestProcessorChain;
     import org.apache.zookeeper.KeeperException;
     import org.apache.zookeeper.data.Stat;
    @@ -47,15 +46,15 @@ class SchemaDesignerSettingsDAO implements SchemaDesignerConstants {
       private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
     
       private final CoreContainer cc;
    +  private final SchemaDesignerConfigSetHelper configSetHelper;
     
    -  SchemaDesignerSettingsDAO(CoreContainer cc) {
    +  SchemaDesignerSettingsDAO(CoreContainer cc, SchemaDesignerConfigSetHelper configSetHelper) {
         this.cc = cc;
    +    this.configSetHelper = configSetHelper;
       }
     
       SchemaDesignerSettings getSettings(String configSet) {
    -    SolrConfig solrConfig =
    -        SolrConfig.readFromResourceLoader(
    -            zkLoaderForConfigSet(configSet), SOLR_CONFIG_XML, true, null);
    +    SolrConfig solrConfig = configSetHelper.loadSolrConfig(configSet);
         return getSettings(solrConfig);
       }
     
    @@ -97,12 +96,14 @@ boolean persistIfChanged(String configSet, SchemaDesignerSettings settings) thro
         }
     
         if (changed) {
    -      ZkController.persistConfigResourceToZooKeeper(
    -          zkLoaderForConfigSet(configSet),
    -          overlay.getVersion(),
    -          ConfigOverlay.RESOURCE_NAME,
    -          overlay.toByteArray(),
    -          true);
    +      try (ZkSolrResourceLoader resourceLoader = configSetHelper.zkLoaderForConfigSet(configSet)) {
    +        ZkController.persistConfigResourceToZooKeeper(
    +            resourceLoader,
    +            overlay.getVersion(),
    +            ConfigOverlay.RESOURCE_NAME,
    +            overlay.toByteArray(),
    +            true);
    +      }
         }
     
         return changed;
    @@ -169,10 +170,4 @@ private boolean hasFieldGuessingURPChain(final SolrConfig solrConfig) {
         }
         return hasPlugin;
       }
    -
    -  private ZkSolrResourceLoader zkLoaderForConfigSet(final String configSet) {
    -    SolrResourceLoader loader = cc.getResourceLoader();
    -    return new ZkSolrResourceLoader(
    -        loader.getInstancePath(), configSet, loader.getClassLoader(), cc.getZkController());
    -  }
     }
    
  • solr/core/src/test/org/apache/solr/handler/designer/TestSchemaDesignerSettingsDAO.java+2 1 modified
    @@ -71,7 +71,8 @@ public void testDAO() throws Exception {
                 .process(cluster.getSolrClient());
         CollectionsHandler.waitForActiveCollection(collection, cc, rsp);
     
    -    SchemaDesignerSettingsDAO dao = new SchemaDesignerSettingsDAO(cc);
    +    SchemaDesignerConfigSetHelper csh = new SchemaDesignerConfigSetHelper(cc, null);
    +    SchemaDesignerSettingsDAO dao = new SchemaDesignerSettingsDAO(cc, csh);
         SchemaDesignerSettings settings = dao.getSettings(configSet);
         assertNotNull(settings);
     
    
  • solr/solr-ref-guide/modules/indexing-guide/pages/schema-designer.adoc+15 0 modified
    @@ -79,6 +79,21 @@ Previously uploaded sample documents are indexed in the temporary collection eve
     Click on the btn:[Edit Documents] button on the *Query Results* panel to load a JSON representation of indexed documents into the text area.
     ====
     
    +=== Trusted Config Sets
    +
    +ConfigSet trust is necessary when loading extra libraries from the `solrconfig.xml` and using certain features of Solr.
    +Refer to the xref:configuration-guide:configsets-api.adoc#configsets-upload[ConfigSet API] section for more information on trusted configSets.
    +
    +Using the Schema Designer API has the same effect on the trust of a ConfigSet as using the xref:configuration-guide:configsets-api.adoc#configsets-upload[ConfigSet Upload API].
    +
    +* If you are authenticated:
    +** If your source configSet **is** trusted, then the temporary configSets you are modifying will remain trusted.
    +** If your source configSet **is not** trusted, then the temporary configSet you are modifying will never be trusted.
    +* If you are unauthenticated:
    +** The temporary configSet created for you will **not** be trusted.
    +
    +When <<publish,publishing the temporary configSet>>, the trust of the temporary configSet is used to set the trust of the permanent configSet.
    +
     === Iteratively Post Sample Documents
     
     If you have sample documents spread across multiple files, you can POST them to the Schema Designer API and then load your schema in the Designer UI to design your schema.
    
  • solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc+1 0 modified
    @@ -91,6 +91,7 @@ The sysProp `-Dsolr.redaction.system.pattern` has been deprecated, use the above
     The `<hiddenSysProps>` solr.xml element under `<metrics>` has been deprecated.
     Instead, use the xref:configuration-guide:configuring-solr-xml.adoc#hiddenSysProps[<hiddenSysProps>] tag under `<solr>`, which accepts a comma-separated string.
     
    +* The xref:indexing-guide:schema-designer.adoc[] now utilizes the same trust model as the xref:configuration-guide:configsets-api.adoc#configsets-upload[ConfigSet Upload API].
     
     === Official Docker Image
     * The customization of the Official Solr Dockerfile has been changed.
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.