Describe the bug
The OAuth2 SSO Callback Server in the CLI (used during login --sso) acts as a global singleton due to its reliance on http.DefaultServeMux. This leads to race conditions and potential port hijacking vulnerabilities.
In cmd/login.go:268-270 (approximate location):
srv := &http.Server{Addr: "localhost:" + strconv.Itoa(port)}
http.HandleFunc("/auth/callback", callbackHandler)
This logic instantiates an http.Server but does not supply a dedicated Handler, meaning it falls back to the process-global http.DefaultServeMux. http.HandleFunc modifies this shared router, and this route is never cleaned up.
The critical impacts include:
- Port Hijacking / Token Exposure: If a malicious process running locally on a multi-tenant machine binds to port 58085 first, the CLI's temporary HTTP server will fail to start (
log.Fatalf), but the callback/authorization details from the user's browser may be successfully routed to the attacker. While PKCE prevents the attacker from directly exchanging the authorization code (as the code_verifier is in the memory of the CLI process), the id_token (passed as r.FormValue("id_token") in the fallback implicit flow) might be extracted directly by the attacking server.
- Global Mux Pollution & Race Conditions: The URL handler
/auth/callback persists permanently inside the process's default HTTP mux. If login is called twice (e.g., in a CI script, or if the first login fails midway), the subsequent calls overwrite the first handler. http.HandleFunc is not completely goroutine-safe when dynamically modifying the mux while a server handles requests. It can incorrectly interleave or fail across consecutive executions in the same process footprint.
Expected behavior
- A locally isolated
http.ServeMux should be used per server instance instead of http.DefaultServeMux. For example:
mux := http.NewServeMux()
mux.HandleFunc("/auth/callback", callbackHandler)
srv := &http.Server{
Addr: "localhost:" + strconv.Itoa(port),
Handler: mux,
}
- The port binding error logic should be explicit: if the expected local port is already bound by another process,
login() should abort safely and alert the user immediately, rather than quietly failing inside a goroutine or leaving the user vulnerable to authorization route hijacking.
Actual behavior
The http.HandleFunc manipulates the global http.DefaultServeMux. The CLI process could leak handlers or have subsequent authentication operations overwrite global states over one another.
How to Reproduce?
- Open a separate terminal and mock an attacker process by listening on port 58085:
- Run the
microcks-cli login --sso command.
- Observe that the OAuth authentication flow continues locally.
- When the browser redirects to
http://localhost:58085/auth/callback..., the attacker nc instance intercepts the HTTP request, collecting the query parameters (which may contain code or id_token depending on the SSO provider mapping configuration).
Alternatively, inspecting the source code validates the reliance on http.DefaultServeMux:
- Find
srv := &http.Server{Addr: "localhost:" + strconv.Itoa(port)} inside cmd/login.go.
- Notice that
http.HandleFunc is being used, making /auth/callback globally registered on http.DefaultServeMux.
Microcks version or git rev
microcks-cli2 (Current main/issue-branch code base as of reported date)
Install method (docker-compose, helm chart, operator, docker-desktop extension,...)
Compiled from source (go build)
Additional information
This issue affects multi-tenant environments where CI/CD setups or shared developer workstations might have concurrent or conflicting listeners. Fixing the HTTP handler scoping provides a resilient boundary.
Describe the bug
The OAuth2 SSO Callback Server in the CLI (used during
login --sso) acts as a global singleton due to its reliance onhttp.DefaultServeMux. This leads to race conditions and potential port hijacking vulnerabilities.In
cmd/login.go:268-270(approximate location):This logic instantiates an
http.Serverbut does not supply a dedicatedHandler, meaning it falls back to the process-globalhttp.DefaultServeMux.http.HandleFuncmodifies this shared router, and this route is never cleaned up.The critical impacts include:
log.Fatalf), but the callback/authorization details from the user's browser may be successfully routed to the attacker. While PKCE prevents the attacker from directly exchanging the authorization code (as thecode_verifieris in the memory of the CLI process), theid_token(passed asr.FormValue("id_token")in the fallback implicit flow) might be extracted directly by the attacking server./auth/callbackpersists permanently inside the process's default HTTP mux. Ifloginis called twice (e.g., in a CI script, or if the first login fails midway), the subsequent calls overwrite the first handler.http.HandleFuncis not completely goroutine-safe when dynamically modifying the mux while a server handles requests. It can incorrectly interleave or fail across consecutive executions in the same process footprint.Expected behavior
http.ServeMuxshould be used per server instance instead ofhttp.DefaultServeMux. For example:login()should abort safely and alert the user immediately, rather than quietly failing inside a goroutine or leaving the user vulnerable to authorization route hijacking.Actual behavior
The
http.HandleFuncmanipulates the globalhttp.DefaultServeMux. The CLI process could leak handlers or have subsequent authentication operations overwrite global states over one another.How to Reproduce?
microcks-cli login --ssocommand.http://localhost:58085/auth/callback..., the attackerncinstance intercepts the HTTP request, collecting the query parameters (which may containcodeorid_tokendepending on the SSO provider mapping configuration).Alternatively, inspecting the source code validates the reliance on
http.DefaultServeMux:srv := &http.Server{Addr: "localhost:" + strconv.Itoa(port)}insidecmd/login.go.http.HandleFuncis being used, making/auth/callbackglobally registered onhttp.DefaultServeMux.Microcks version or git rev
microcks-cli2 (Current main/issue-branch code base as of reported date)
Install method (
docker-compose,helm chart,operator,docker-desktop extension,...)Compiled from source (
go build)Additional information
This issue affects multi-tenant environments where CI/CD setups or shared developer workstations might have concurrent or conflicting listeners. Fixing the HTTP handler scoping provides a resilient boundary.