Follow-up from #1902 (CodeRabbit, thread).
Problem
client.rs::new() calls config.tls.build() (→ tls::Client::verification()) eagerly for every backend, and QuicheClient::new() resolves verification() too. Both run before any connect() sees the URL scheme. So in a roots-less configuration — --tls-system-roots=false with no --tls-root and no --tls-fingerprint — verification() returns NoRoots and client construction fails, even though an http:// URL would fetch /certificate.sha256 and pin it (bypassing CA roots) for that connection.
Net effect: the http:// insecure-bootstrap path is unusable in environments with no system/custom roots. It's fail-closed (errors rather than connecting insecurely) and niche, but it's a real functional limitation and it's consistent across quinn/noq/quiche.
Fix sketch
Defer trust-root resolution to per-connection, after the URL scheme is known, so a fetched http:// pin can satisfy the connection without resolved CA roots. Touches client.rs (which currently builds the rustls config once and shares it), all three backends, and the websocket fallback path — hence deferred out of #1902.
Not a security issue (it only over-restricts).
(Written by Claude)
Follow-up from #1902 (CodeRabbit, thread).
Problem
client.rs::new()callsconfig.tls.build()(→tls::Client::verification()) eagerly for every backend, andQuicheClient::new()resolvesverification()too. Both run before anyconnect()sees the URL scheme. So in a roots-less configuration —--tls-system-roots=falsewith no--tls-rootand no--tls-fingerprint—verification()returnsNoRootsand client construction fails, even though anhttp://URL would fetch/certificate.sha256and pin it (bypassing CA roots) for that connection.Net effect: the
http://insecure-bootstrap path is unusable in environments with no system/custom roots. It's fail-closed (errors rather than connecting insecurely) and niche, but it's a real functional limitation and it's consistent across quinn/noq/quiche.Fix sketch
Defer trust-root resolution to per-connection, after the URL scheme is known, so a fetched
http://pin can satisfy the connection without resolved CA roots. Touchesclient.rs(which currently builds the rustls config once and shares it), all three backends, and the websocket fallback path — hence deferred out of #1902.Not a security issue (it only over-restricts).
(Written by Claude)