VYPR
Critical severityNVD Advisory· Published Apr 17, 2023· Updated Oct 21, 2024

Apache Spark proxy-user privilege escalation from malicious configuration class

CVE-2023-22946

Description

In Apache Spark versions prior to 3.4.0, applications using spark-submit can specify a 'proxy-user' to run as, limiting privileges. The application can execute code with the privileges of the submitting user, however, by providing malicious configuration-related classes on the classpath. This affects architectures relying on proxy-user, for example those using Apache Livy to manage submitted applications.

Update to Apache Spark 3.4.0 or later, and ensure that spark.submit.proxyUser.allowCustomClasspathInClusterMode is set to its default of "false", and is not overridden by submitted applications.

AI Insight

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

Privilege escalation in Apache Spark <3.4.0 allows a proxy-user application to execute code as the submitting user via a malicious classpath.

Vulnerability

CVE-2023-22946 is a privilege escalation vulnerability in Apache Spark versions prior to 3.4.0. The root cause is that when spark-submit is used with a 'proxy-user' (a user identity with limited privileges), the application can still provide malicious configuration-related classes on the classpath. This allows the application to execute arbitrary code with the full privileges of the submitting user, effectively bypassing the intended privilege restriction [3].

Exploitation

To exploit this vulnerability, an attacker must be able to submit an application via spark-submit that specifies both a proxy-user and a custom classpath containing malicious classes. The attack surface includes environments relying on proxy-user delegation, such as those using Apache Livy to manage submitted applications [1]. No additional authentication is needed beyond what is required to submit a job; the submitted application can then run code with the submitting user's identity and permissions.

Impact

Successful exploitation allows the application to execute arbitrary code with the privileges of the user who submitted the Spark job, not the intended proxy-user. This can lead to unauthorized data access, privilege escalation, and potential compromise of the entire cluster if the submitting user has broad permissions.

Mitigation

The vulnerability is fixed in Apache Spark 3.4.0 and later [2]. Users should upgrade to Spark 3.4.0 or a patched 3.3.x release containing the backport (such as 3.3.3). The default configuration now disallows arbitrary custom classpaths with proxy users in cluster mode via the setting spark.submit.proxyUser.allowCustomClasspathInClusterMode, which should remain set to false [1][4]. No workarounds exist other than upgrading and ensuring the default configuration is not overridden.

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.spark:spark-core_2.12Maven
< 3.3.33.3.3
org.apache.spark:spark-core_2.13Maven
< 3.3.33.3.3
pysparkPyPI
< 3.3.23.3.2

Affected products

5

Patches

2
909da96e1471

[SPARK-41958][CORE] Disallow arbitrary custom classpath with proxy user in cluster mode

https://github.com/apache/sparkPeter TothJan 10, 2023via ghsa
2 files changed · +22 0
  • core/src/main/scala/org/apache/spark/deploy/SparkSubmit.scala+15 0 modified
    @@ -306,6 +306,10 @@ private[spark] class SparkSubmit extends Logging {
         val isKubernetesClient = clusterManager == KUBERNETES && deployMode == CLIENT
         val isKubernetesClusterModeDriver = isKubernetesClient &&
           sparkConf.getBoolean("spark.kubernetes.submitInDriver", false)
    +    val isCustomClasspathInClusterModeDisallowed =
    +      !sparkConf.get(ALLOW_CUSTOM_CLASSPATH_BY_PROXY_USER_IN_CLUSTER_MODE) &&
    +      args.proxyUser != null &&
    +      (isYarnCluster || isMesosCluster || isStandAloneCluster || isKubernetesCluster)
     
         if (!isMesosCluster && !isStandAloneCluster) {
           // Resolve maven dependencies if there are any and add classpath to jars. Add them to py-files
    @@ -887,6 +891,13 @@ private[spark] class SparkSubmit extends Logging {
     
         sparkConf.set("spark.app.submitTime", System.currentTimeMillis().toString)
     
    +    if (childClasspath.nonEmpty && isCustomClasspathInClusterModeDisallowed) {
    +      childClasspath.clear()
    +      logWarning(s"Ignore classpath ${childClasspath.mkString(", ")} with proxy user specified " +
    +        s"in Cluster mode when ${ALLOW_CUSTOM_CLASSPATH_BY_PROXY_USER_IN_CLUSTER_MODE.key} is " +
    +        s"disabled")
    +    }
    +
         (childArgs.toSeq, childClasspath.toSeq, sparkConf, childMainClass)
       }
     
    @@ -940,6 +951,10 @@ private[spark] class SparkSubmit extends Logging {
           logInfo(s"Classpath elements:\n${childClasspath.mkString("\n")}")
           logInfo("\n")
         }
    +    assert(!(args.deployMode == "cluster" && args.proxyUser != null && childClasspath.nonEmpty) ||
    +      sparkConf.get(ALLOW_CUSTOM_CLASSPATH_BY_PROXY_USER_IN_CLUSTER_MODE),
    +      s"Classpath of spark-submit should not change in cluster mode if proxy user is specified " +
    +        s"when ${ALLOW_CUSTOM_CLASSPATH_BY_PROXY_USER_IN_CLUSTER_MODE.key} is disabled")
         val loader = getSubmitClassLoader(sparkConf)
         for (jar <- childClasspath) {
           addJarToClasspath(jar, loader)
    
  • core/src/main/scala/org/apache/spark/internal/config/package.scala+7 0 modified
    @@ -2461,4 +2461,11 @@ package object config {
           .version("3.4.0")
           .timeConf(TimeUnit.MILLISECONDS)
           .createWithDefaultString("5s")
    +
    +  private[spark] val ALLOW_CUSTOM_CLASSPATH_BY_PROXY_USER_IN_CLUSTER_MODE =
    +    ConfigBuilder("spark.submit.proxyUser.allowCustomClasspathInClusterMode")
    +      .internal()
    +      .version("3.4.0")
    +      .booleanConf
    +      .createWithDefault(false)
     }
    
bfba57724d25

Backporting fix for SPARK-41958 to 3.3 branch from #39474

https://github.com/degant/sparkPeter TothJan 10, 2023via ghsa
2 files changed · +22 0
  • core/src/main/scala/org/apache/spark/deploy/SparkSubmit.scala+15 0 modified
    @@ -310,6 +310,10 @@ private[spark] class SparkSubmit extends Logging {
         val isKubernetesClient = clusterManager == KUBERNETES && deployMode == CLIENT
         val isKubernetesClusterModeDriver = isKubernetesClient &&
           sparkConf.getBoolean("spark.kubernetes.submitInDriver", false)
    +    val isCustomClasspathInClusterModeDisallowed =
    +      !sparkConf.get(ALLOW_CUSTOM_CLASSPATH_BY_PROXY_USER_IN_CLUSTER_MODE) &&
    +      args.proxyUser != null &&
    +      (isYarnCluster || isMesosCluster || isStandAloneCluster || isKubernetesCluster)
     
         if (!isMesosCluster && !isStandAloneCluster) {
           // Resolve maven dependencies if there are any and add classpath to jars. Add them to py-files
    @@ -870,6 +874,13 @@ private[spark] class SparkSubmit extends Logging {
     
         sparkConf.set("spark.app.submitTime", System.currentTimeMillis().toString)
     
    +    if (childClasspath.nonEmpty && isCustomClasspathInClusterModeDisallowed) {
    +      childClasspath.clear()
    +      logWarning(s"Ignore classpath ${childClasspath.mkString(", ")} with proxy user specified " +
    +        s"in Cluster mode when ${ALLOW_CUSTOM_CLASSPATH_BY_PROXY_USER_IN_CLUSTER_MODE.key} is " +
    +        s"disabled")
    +    }
    +
         (childArgs.toSeq, childClasspath.toSeq, sparkConf, childMainClass)
       }
     
    @@ -923,6 +934,10 @@ private[spark] class SparkSubmit extends Logging {
           logInfo(s"Classpath elements:\n${childClasspath.mkString("\n")}")
           logInfo("\n")
         }
    +    assert(!(args.deployMode == "cluster" && args.proxyUser != null && childClasspath.nonEmpty) ||
    +      sparkConf.get(ALLOW_CUSTOM_CLASSPATH_BY_PROXY_USER_IN_CLUSTER_MODE),
    +      s"Classpath of spark-submit should not change in cluster mode if proxy user is specified " +
    +        s"when ${ALLOW_CUSTOM_CLASSPATH_BY_PROXY_USER_IN_CLUSTER_MODE.key} is disabled")
         val loader = getSubmitClassLoader(sparkConf)
         for (jar <- childClasspath) {
           addJarToClasspath(jar, loader)
    
  • core/src/main/scala/org/apache/spark/internal/config/package.scala+7 0 modified
    @@ -2355,4 +2355,11 @@ package object config {
           .version("3.3.0")
           .intConf
           .createWithDefault(5)
    +
    +  private[spark] val ALLOW_CUSTOM_CLASSPATH_BY_PROXY_USER_IN_CLUSTER_MODE =
    +    ConfigBuilder("spark.submit.proxyUser.allowCustomClasspathInClusterMode")
    +      .internal()
    +      .version("3.3.3")
    +      .booleanConf
    +      .createWithDefault(false)
     }
    

Vulnerability mechanics

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

References

9

News mentions

0

No linked articles in our index yet.