From fbeae8bb1111246702da98451c902b4b68582c03 Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Sun, 10 May 2026 13:37:07 +0200 Subject: [PATCH] fix(security): make upstream TLS verification opt-in via settings flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CodeQL alerts #70 and #71 (go/disabled-certificate-check) flagged the hard-coded `InsecureSkipVerify: true` in handlers_proxy.go (the /proxy/{url} reverse proxy) and mirror_middleware.go (the parity-check mirror). Both target *.bose.com whose certificate chain is becoming unreliable post end-of-service, but unconditionally disabling verification is still wrong: a deployment that doesn't actually need the bypass loses TLS hygiene for free. Add an `AllowInsecureUpstreamTLS bool` field to datastore.Settings, default false. Read it in both call sites — they aren't on a hot path — and pass the value as InsecureSkipVerify. CodeQL accepts the configurable boolean as a non-flag (vs. the previously hard-coded `true`), and the runtime behaviour now defaults to verifying certificates with an explicit opt-in for the broken-chain scenario. Behaviour change: TLS upstream traffic is verified by default. Anyone relying on the previous always-skip behaviour can re-enable it by setting `"allow_insecure_upstream_tls": true` in settings.json. Co-Authored-By: Claude Opus 4.7 (1M context) --- pkg/service/datastore/datastore.go | 6 ++++++ pkg/service/handlers/handlers_proxy.go | 9 ++++++++- pkg/service/handlers/mirror_middleware.go | 8 +++++++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/pkg/service/datastore/datastore.go b/pkg/service/datastore/datastore.go index f709fa4..971dfc6 100644 --- a/pkg/service/datastore/datastore.go +++ b/pkg/service/datastore/datastore.go @@ -1800,6 +1800,12 @@ type Settings struct { AmazonClientID string `json:"amazon_client_id,omitempty"` AmazonClientSecret string `json:"amazon_client_secret,omitempty"` AmazonRedirectURI string `json:"amazon_redirect_uri,omitempty"` + + // AllowInsecureUpstreamTLS, when true, disables TLS certificate verification + // for the upstream Bose-cloud proxy and mirror traffic. The default (false) + // keeps verification on; opt in only when the upstream certificate chain is + // broken (post end-of-service) and a temporary unblock is required. + AllowInsecureUpstreamTLS bool `json:"allow_insecure_upstream_tls,omitempty"` } // GetSettings retrieves the global service settings. diff --git a/pkg/service/handlers/handlers_proxy.go b/pkg/service/handlers/handlers_proxy.go index 2af5bc7..ce03d6f 100644 --- a/pkg/service/handlers/handlers_proxy.go +++ b/pkg/service/handlers/handlers_proxy.go @@ -62,6 +62,13 @@ func (s *Server) ServeProxy(target *url.URL) http.HandlerFunc { r.Body = io.NopCloser(bytes.NewBuffer(reqBody)) } + // AllowInsecureUpstreamTLS is opt-in via settings.json — defaults to + // false so the upstream certificate chain is verified normally. The + // opt-in exists for deployments stuck behind a broken Bose-cloud + // chain post end-of-service. + settings, _ := s.ds.GetSettings() + insecure := settings.AllowInsecureUpstreamTLS + rp := &httputil.ReverseProxy{ Rewrite: func(pr *httputil.ProxyRequest) { pr.SetURL(target) @@ -77,7 +84,7 @@ func (s *Server) ServeProxy(target *url.URL) http.HandlerFunc { lp.LogRequest(pr.Out) }, Transport: &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + TLSClientConfig: &tls.Config{InsecureSkipVerify: insecure}, }, } diff --git a/pkg/service/handlers/mirror_middleware.go b/pkg/service/handlers/mirror_middleware.go index 0ee3ada..1767daa 100644 --- a/pkg/service/handlers/mirror_middleware.go +++ b/pkg/service/handlers/mirror_middleware.go @@ -271,6 +271,12 @@ func (s *Server) performMirror(r *http.Request) *mirrorResponseRecorder { return nil } + // AllowInsecureUpstreamTLS is opt-in via settings.json — defaults to + // false so verification stays on. The opt-in exists for deployments + // stuck behind a broken Bose-cloud certificate chain post EOS. + settings, _ := s.ds.GetSettings() + insecure := settings.AllowInsecureUpstreamTLS + // Create a proxy that doesn't write to the original ResponseWriter proxy := &httputil.ReverseProxy{ Rewrite: func(pr *httputil.ProxyRequest) { @@ -279,7 +285,7 @@ func (s *Server) performMirror(r *http.Request) *mirrorResponseRecorder { pr.Out.Header.Set("X-Mirror-Request", "true") }, Transport: &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + TLSClientConfig: &tls.Config{InsecureSkipVerify: insecure}, }, }