When a query result has endpoints with non-empty locations, ArrowFlightSqlClientHandler.getStreams clones the connection's Builder and connects to each advertised location. The clone keeps username/password, token and the OAuth config, and encryption is then set from the location scheme alone:
.withEncryption(endpointUri.getScheme().equals(LocationSchemes.GRPC_TLS))
So a location with any other scheme (grpc+tcp:// in particular) turns encryption off for that endpoint client even when the connection was opened with useEncryption=true. build() then runs the handshake and sends the credentials over the plaintext channel to the advertised host.
The documented meaning of useEncryption (default true) is "Whether to use TLS (the default is an encrypted connection)", so a server-supplied string silently overriding it is surprising: a compromised or hostile Flight SQL server, or anything able to influence the FlightInfo it returns, can have the driver hand over the user's credentials in cleartext, and a passive attacker on the endpoint path can read them.
Reproduced against a handler built with withEncryption(true) plus a username/password, given a FlightInfo with one endpoint at Location.forGrpcInsecure(...): the driver attempts the connection and reaches ClientHandshakeWrapper on the unencrypted channel instead of refusing it.
arrow-flight-sql-jdbc-driver, main.
When a query result has endpoints with non-empty locations,
ArrowFlightSqlClientHandler.getStreamsclones the connection'sBuilderand connects to each advertised location. The clone keepsusername/password,tokenand the OAuth config, and encryption is then set from the location scheme alone:So a location with any other scheme (
grpc+tcp://in particular) turns encryption off for that endpoint client even when the connection was opened withuseEncryption=true.build()then runs the handshake and sends the credentials over the plaintext channel to the advertised host.The documented meaning of
useEncryption(defaulttrue) is "Whether to use TLS (the default is an encrypted connection)", so a server-supplied string silently overriding it is surprising: a compromised or hostile Flight SQL server, or anything able to influence theFlightInfoit returns, can have the driver hand over the user's credentials in cleartext, and a passive attacker on the endpoint path can read them.Reproduced against a handler built with
withEncryption(true)plus a username/password, given aFlightInfowith one endpoint atLocation.forGrpcInsecure(...): the driver attempts the connection and reachesClientHandshakeWrapperon the unencrypted channel instead of refusing it.arrow-flight-sql-jdbc-driver, main.