diff --git a/pkg/service/handlers/handlers_bmx_siriusxm.go b/pkg/service/handlers/handlers_bmx_siriusxm.go index a4c25fe..b9e2d5a 100644 --- a/pkg/service/handlers/handlers_bmx_siriusxm.go +++ b/pkg/service/handlers/handlers_bmx_siriusxm.go @@ -21,10 +21,15 @@ import ( // HandleSiriusXMLiveAdapter returns the SIRIUSXM_EVEREST service descriptor // from bmx_services.json for the bare live-adapter base URL. +// +// NB: we log the *presence* of the Authorization header, not its value — +// the header carries a long-lived bearer token (margeAuthToken) that +// would be replayable if a logfile got captured. CodeQL +// go/clear-text-logging caught the original `auth=%q` shape. func (s *Server) HandleSiriusXMLiveAdapter(w http.ResponseWriter, r *http.Request) { - log.Printf("[BMX SiriusXM] %s %s ua=%q auth=%q query=%q", + log.Printf("[BMX SiriusXM] %s %s ua=%q authPresent=%t query=%q", r.Method, r.URL.Path, r.UserAgent(), - r.Header.Get("Authorization"), r.URL.RawQuery) + r.Header.Get("Authorization") != "", r.URL.RawQuery) svc, err := extractBMXService(bmxServicesJSON, "SIRIUSXM_EVEREST") if err != nil { @@ -45,9 +50,9 @@ func (s *Server) HandleSiriusXMLiveAdapter(w http.ResponseWriter, r *http.Reques // pass — the _links in the descriptor publish /availability, /token, // /navigate, /logout; playback URLs come dynamically from navigate. func (s *Server) HandleSiriusXMLiveAdapterSubpath(w http.ResponseWriter, r *http.Request) { - log.Printf("[BMX SiriusXM] UNIMPLEMENTED %s %s ua=%q auth=%q query=%q", + log.Printf("[BMX SiriusXM] UNIMPLEMENTED %s %s ua=%q authPresent=%t query=%q", r.Method, r.URL.Path, r.UserAgent(), - r.Header.Get("Authorization"), r.URL.RawQuery) + r.Header.Get("Authorization") != "", r.URL.RawQuery) http.Error(w, "not implemented", http.StatusNotFound) } diff --git a/pkg/service/stockholm/handler.go b/pkg/service/stockholm/handler.go index 0e00da3..75b1d0b 100644 --- a/pkg/service/stockholm/handler.go +++ b/pkg/service/stockholm/handler.go @@ -64,6 +64,19 @@ func New(stockholmDir, workspaceRoot, backendURL, basePath string) (*Handler, er } basePath = strings.TrimRight(basePath, "/") + + // Defence in depth: basePath is operator-provided (CLI flag / + // STOCKHOLM_BASE_PATH env var), not request input — but if it + // were ever set to "//evil.com" (typo or hostile env injection) + // the bare-path redirect below would go scheme-relative to + // evil.com. Reject any leading-double-slash and any backslash + // so the redirect target can only ever be an absolute local + // path. CodeQL go/bad-redirect-check raised the original + // concern. + if strings.HasPrefix(basePath, "//") || strings.HasPrefix(basePath, "/\\") || strings.ContainsAny(basePath, "\\") { + return nil, fmt.Errorf("invalid stockholm base path %q: must be an absolute path starting with a single '/'", basePath) + } + cfg.BasePath = basePath state.SeedFromEnv(cfg)