From 4577390130b351e56dd0d031ef3a7effd04d82cc Mon Sep 17 00:00:00 2001 From: Hugo Aboud Date: Tue, 19 Aug 2025 16:16:01 -0300 Subject: [PATCH 1/2] Sanitize credentials on websocket error messages --- internal/api/ws/ws.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/api/ws/ws.go b/internal/api/ws/ws.go index 1d945bfe..5a7d34be 100644 --- a/internal/api/ws/ws.go +++ b/internal/api/ws/ws.go @@ -8,6 +8,7 @@ import ( "strings" "sync" "time" + "regexp" "github.com/AlexxIT/go2rtc/internal/api" "github.com/AlexxIT/go2rtc/internal/app" @@ -132,7 +133,11 @@ func apiWS(w http.ResponseWriter, r *http.Request) { if handler := wsHandlers[msg.Type]; handler != nil { go func() { if err = handler(tr, msg); err != nil { - tr.Write(&Message{Type: "error", Value: msg.Type + ": " + err.Error()}) + // Some streams such as ffmpeg might return credentials on error messages + errMsg := err.Error() + sanitizer := regexp.MustCompile(`(\w+)://(.*)@`) + errMsg = sanitizer.ReplaceAllString(errMsg, "$1://******@") + tr.Write(&Message{Type: "error", Value: msg.Type + ": " + errMsg}) } }() } From 8b4df5f02c7882256799f8c769e5c1e999d8bd6b Mon Sep 17 00:00:00 2001 From: Alex X Date: Fri, 19 Sep 2025 15:21:02 +0300 Subject: [PATCH 2/2] Code refactoring for #1841 --- internal/api/ws/ws.go | 7 ++----- pkg/core/core_test.go | 14 ++++++++++++++ pkg/core/helpers.go | 12 ++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/internal/api/ws/ws.go b/internal/api/ws/ws.go index 5a7d34be..981d1b41 100644 --- a/internal/api/ws/ws.go +++ b/internal/api/ws/ws.go @@ -8,10 +8,10 @@ import ( "strings" "sync" "time" - "regexp" "github.com/AlexxIT/go2rtc/internal/api" "github.com/AlexxIT/go2rtc/internal/app" + "github.com/AlexxIT/go2rtc/pkg/core" "github.com/gorilla/websocket" "github.com/rs/zerolog" ) @@ -133,10 +133,7 @@ func apiWS(w http.ResponseWriter, r *http.Request) { if handler := wsHandlers[msg.Type]; handler != nil { go func() { if err = handler(tr, msg); err != nil { - // Some streams such as ffmpeg might return credentials on error messages - errMsg := err.Error() - sanitizer := regexp.MustCompile(`(\w+)://(.*)@`) - errMsg = sanitizer.ReplaceAllString(errMsg, "$1://******@") + errMsg := core.StripUserinfo(err.Error()) tr.Write(&Message{Type: "error", Value: msg.Type + ": " + errMsg}) } }() diff --git a/pkg/core/core_test.go b/pkg/core/core_test.go index 4a05380a..e7845ca7 100644 --- a/pkg/core/core_test.go +++ b/pkg/core/core_test.go @@ -118,3 +118,17 @@ func TestName(t *testing.T) { // stage3 _ = prod2.Stop() } + +func TestStripUserinfo(t *testing.T) { + s := `streams: + test: + - ffmpeg:rtsp://username:password@10.1.2.3:554/stream1 + - ffmpeg:rtsp://10.1.2.3:554/stream1@#video=copy +` + s = StripUserinfo(s) + require.Equal(t, `streams: + test: + - ffmpeg:rtsp://***@10.1.2.3:554/stream1 + - ffmpeg:rtsp://10.1.2.3:554/stream1@#video=copy +`, s) +} diff --git a/pkg/core/helpers.go b/pkg/core/helpers.go index 72afe897..161a5504 100644 --- a/pkg/core/helpers.go +++ b/pkg/core/helpers.go @@ -2,6 +2,7 @@ package core import ( "crypto/rand" + "regexp" "runtime" "strconv" "strings" @@ -77,3 +78,14 @@ func Caller() string { _, file, line, _ := runtime.Caller(1) return file + ":" + strconv.Itoa(line) } + +const ( + unreserved = `A-Za-z0-9-._~` + subdelims = `!$&'()*+,;=` + userinfo = unreserved + subdelims + `%:` +) + +func StripUserinfo(s string) string { + sanitizer := regexp.MustCompile(`://[` + userinfo + `]+@`) + return sanitizer.ReplaceAllString(s, `://***@`) +}