From dd7580b454b7e9358266967e43c4043a32c7de7f Mon Sep 17 00:00:00 2001 From: Raja Subramanian Date: Tue, 26 May 2026 20:32:11 +0530 Subject: [PATCH 1/2] Protect against nil clientInfo (#4546) --- pkg/service/utils.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/service/utils.go b/pkg/service/utils.go index 52433f329..e129e2f83 100644 --- a/pkg/service/utils.go +++ b/pkg/service/utils.go @@ -246,6 +246,10 @@ func getUserAgentParser() *uaparser.Parser { } func AugmentClientInfo(ci *livekit.ClientInfo, req *http.Request) { + if ci == nil { + return + } + // get real address (forwarded http header) - check Cloudflare headers first, fall back to X-Forwarded-For ci.Address = GetClientIP(req) From 222177a9e43f522e7814814c3376564b40780f9e Mon Sep 17 00:00:00 2001 From: Paul Wells Date: Tue, 26 May 2026 08:34:15 -0700 Subject: [PATCH 2/2] service: prevent nil deref in validate with wrapped join request (#4547) When a client hits /rtc/v[01]/validate with a base64 WrappedJoinRequest whose embedded JoinRequest.ClientInfo is unset, validateInternal called AugmentClientInfo with a nil *ClientInfo and panicked at ci.Address = GetClientIP(req). The non-wrapped branch already allocates via ParseClientInfo; do the same here so pi.Client always gets at least the resolved client Address. --- pkg/service/rtcservice.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/service/rtcservice.go b/pkg/service/rtcservice.go index 04685b1e9..6f18356df 100644 --- a/pkg/service/rtcservice.go +++ b/pkg/service/rtcservice.go @@ -254,6 +254,9 @@ func (s *RTCService) validateInternal( } else { lgr.Debugw("processing join request", "joinRequest", logger.Proto(joinRequest)) + if joinRequest.ClientInfo == nil { + joinRequest.ClientInfo = &livekit.ClientInfo{} + } AugmentClientInfo(joinRequest.ClientInfo, r) pi.Client = joinRequest.ClientInfo