L. C. Hsieh created SPARK-58658:
-----------------------------------

             Summary: Do not return spark.connect.authenticate.token from the 
Config RPC
                 Key: SPARK-58658
                 URL: https://issues.apache.org/jira/browse/SPARK-58658
             Project: Spark
          Issue Type: Improvement
          Components: Connect
    Affects Versions: 5.0.0
            Reporter: L. C. Hsieh


The Spark Connect Config RPC hands back any configuration key the session 
holds, including {{spark.connect.authenticate.token}}:

{code}
spark.conf.get("spark.connect.authenticate.token")   // returns the token
{code}

The key reaches the session config because {{SQLConf.mergeSparkConf}} copies 
every {{SparkConf}} entry -- static ones included -- into it, and 
{{SparkConnectConfigHandler}}'s read paths ({{handleGet}}, {{handleGetOption}}, 
{{handleGetWithDefault}}, {{handleGetAll}}) apply no denylist. 
{{RuntimeConfig}} guards *writes* to static configs with 
{{requireNonStaticConf}}, but reads are unguarded.

This is not a vulnerability in the client-to-server deployment Spark itself 
documents: the token is a client credential, and a client that can call the 
Config RPC has already presented it, so reading it back discloses nothing.

It does matter for deployments that place a proxy in front of Spark Connect and 
reuse this config as a secret shared between the proxy and the servers, with 
end users authenticating to the proxy by other means. There, any user the proxy 
admits can read the token out of a backend and then connect to that backend 
directly, bypassing whatever the proxy enforces. That reinterpretation of the 
config is the deployment's own, not something Spark promises -- which is why 
this is filed as an improvement rather than a security issue -- but a server 
not disclosing its own credential is the better default regardless, and it is 
cheap.

*Proposed change:* report the key as unset on every read path: {{Get}} and 
{{GetOption}} return no value, {{GetWithDefault}} returns the caller's default, 
and {{GetAll}} omits it. {{Set}}/{{Unset}} already reject it via 
{{requireNonStaticConf}}, and {{IsModifiable}} returns false for a static 
config without disclosing anything.

Note for anyone implementing this: {{handleGetAll}} strips the requested prefix 
from the keys it returns, so the filter has to run on the full key before the 
prefix is removed.




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to