fix: WebsocketListener nil panic and OIDC auth data race (#5204)

- pkg/util/net/websocket.go: store ln parameter in struct to prevent
  nil pointer panic when Addr() is called
- pkg/auth/oidc.go: replace unsynchronized []string with map + RWMutex
  for subjectsFromLogin to fix data race across concurrent connections
This commit is contained in:
fatedier
2026-03-06 16:51:52 +08:00
committed by GitHub
parent 8f633fe363
commit cb459b02b6
2 changed files with 13 additions and 8 deletions

View File

@@ -23,6 +23,7 @@ import (
"net/url" "net/url"
"os" "os"
"slices" "slices"
"sync"
"github.com/coreos/go-oidc/v3/oidc" "github.com/coreos/go-oidc/v3/oidc"
"golang.org/x/oauth2" "golang.org/x/oauth2"
@@ -205,7 +206,8 @@ type OidcAuthConsumer struct {
additionalAuthScopes []v1.AuthScope additionalAuthScopes []v1.AuthScope
verifier TokenVerifier verifier TokenVerifier
subjectsFromLogin []string mu sync.RWMutex
subjectsFromLogin map[string]struct{}
} }
func NewTokenVerifier(cfg v1.AuthOIDCServerConfig) TokenVerifier { func NewTokenVerifier(cfg v1.AuthOIDCServerConfig) TokenVerifier {
@@ -226,7 +228,7 @@ func NewOidcAuthVerifier(additionalAuthScopes []v1.AuthScope, verifier TokenVeri
return &OidcAuthConsumer{ return &OidcAuthConsumer{
additionalAuthScopes: additionalAuthScopes, additionalAuthScopes: additionalAuthScopes,
verifier: verifier, verifier: verifier,
subjectsFromLogin: []string{}, subjectsFromLogin: make(map[string]struct{}),
} }
} }
@@ -235,9 +237,9 @@ func (auth *OidcAuthConsumer) VerifyLogin(loginMsg *msg.Login) (err error) {
if err != nil { if err != nil {
return fmt.Errorf("invalid OIDC token in login: %v", err) return fmt.Errorf("invalid OIDC token in login: %v", err)
} }
if !slices.Contains(auth.subjectsFromLogin, token.Subject) { auth.mu.Lock()
auth.subjectsFromLogin = append(auth.subjectsFromLogin, token.Subject) auth.subjectsFromLogin[token.Subject] = struct{}{}
} auth.mu.Unlock()
return nil return nil
} }
@@ -246,11 +248,13 @@ func (auth *OidcAuthConsumer) verifyPostLoginToken(privilegeKey string) (err err
if err != nil { if err != nil {
return fmt.Errorf("invalid OIDC token in ping: %v", err) return fmt.Errorf("invalid OIDC token in ping: %v", err)
} }
if !slices.Contains(auth.subjectsFromLogin, token.Subject) { auth.mu.RLock()
_, ok := auth.subjectsFromLogin[token.Subject]
auth.mu.RUnlock()
if !ok {
return fmt.Errorf("received different OIDC subject in login and ping. "+ return fmt.Errorf("received different OIDC subject in login and ping. "+
"original subjects: %s, "+
"new subject: %s", "new subject: %s",
auth.subjectsFromLogin, token.Subject) token.Subject)
} }
return nil return nil
} }

View File

@@ -26,6 +26,7 @@ type WebsocketListener struct {
// ln: tcp listener for websocket connections // ln: tcp listener for websocket connections
func NewWebsocketListener(ln net.Listener) (wl *WebsocketListener) { func NewWebsocketListener(ln net.Listener) (wl *WebsocketListener) {
wl = &WebsocketListener{ wl = &WebsocketListener{
ln: ln,
acceptCh: make(chan net.Conn), acceptCh: make(chan net.Conn),
} }