Strip Userinfo from log entries and errors #2051

This commit is contained in:
Alex X
2026-01-21 17:14:14 +03:00
parent 6eeba1ae4c
commit de157eb144
3 changed files with 32 additions and 33 deletions
+2 -2
View File
@@ -11,7 +11,7 @@ import (
"github.com/AlexxIT/go2rtc/internal/api" "github.com/AlexxIT/go2rtc/internal/api"
"github.com/AlexxIT/go2rtc/internal/app" "github.com/AlexxIT/go2rtc/internal/app"
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/creds"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/rs/zerolog" "github.com/rs/zerolog"
) )
@@ -133,7 +133,7 @@ func apiWS(w http.ResponseWriter, r *http.Request) {
if handler := wsHandlers[msg.Type]; handler != nil { if handler := wsHandlers[msg.Type]; handler != nil {
go func() { go func() {
if err = handler(tr, msg); err != nil { if err = handler(tr, msg); err != nil {
errMsg := core.StripUserinfo(err.Error()) errMsg := creds.SecretString(err.Error())
tr.Write(&Message{Type: "error", Value: msg.Type + ": " + errMsg}) tr.Write(&Message{Type: "error", Value: msg.Type + ": " + errMsg})
} }
}() }()
-12
View File
@@ -2,7 +2,6 @@ package core
import ( import (
"crypto/rand" "crypto/rand"
"regexp"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
@@ -93,14 +92,3 @@ func Caller() string {
_, file, line, _ := runtime.Caller(1) _, file, line, _ := runtime.Caller(1)
return file + ":" + strconv.Itoa(line) 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, `://***@`)
}
+30 -19
View File
@@ -3,6 +3,7 @@ package creds
import ( import (
"io" "io"
"net/http" "net/http"
"regexp"
"slices" "slices"
"strings" "strings"
"sync" "sync"
@@ -27,6 +28,7 @@ func AddSecret(value string) {
var secrets []string var secrets []string
var secretsMu sync.Mutex var secretsMu sync.Mutex
var secretsReplacer *strings.Replacer var secretsReplacer *strings.Replacer
var userinfoRegexp *regexp.Regexp
func getReplacer() *strings.Replacer { func getReplacer() *strings.Replacer {
secretsMu.Lock() secretsMu.Lock()
@@ -40,14 +42,33 @@ func getReplacer() *strings.Replacer {
secretsReplacer = strings.NewReplacer(oldnew...) secretsReplacer = strings.NewReplacer(oldnew...)
} }
if userinfoRegexp == nil {
userinfoRegexp = regexp.MustCompile(`://[` + userinfo + `]+@`)
}
return secretsReplacer return secretsReplacer
} }
// Uniform Resource Identifier (URI)
// https://datatracker.ietf.org/doc/html/rfc3986
const (
unreserved = `A-Za-z0-9-._~`
subdelims = `!$&'()*+,;=`
userinfo = unreserved + subdelims + `%:`
)
func SecretString(s string) string { func SecretString(s string) string {
re := getReplacer() re := getReplacer()
s = userinfoRegexp.ReplaceAllString(s, `://***@`)
return re.Replace(s) return re.Replace(s)
} }
func SecretWrite(w io.Writer, s string) (n int, err error) {
re := getReplacer()
s = userinfoRegexp.ReplaceAllString(s, `://***@`)
return re.WriteString(w, s)
}
func SecretWriter(w io.Writer) io.Writer { func SecretWriter(w io.Writer) io.Writer {
return &secretWriter{w} return &secretWriter{w}
} }
@@ -57,27 +78,17 @@ type secretWriter struct {
} }
func (s *secretWriter) Write(b []byte) (int, error) { func (s *secretWriter) Write(b []byte) (int, error) {
re := getReplacer() return SecretWrite(s.w, string(b))
return re.WriteString(s.w, string(b))
}
type secretResponse struct {
w http.ResponseWriter
}
func (s *secretResponse) Header() http.Header {
return s.w.Header()
}
func (s *secretResponse) Write(b []byte) (int, error) {
re := getReplacer()
return re.WriteString(s.w, string(b))
}
func (s *secretResponse) WriteHeader(statusCode int) {
s.w.WriteHeader(statusCode)
} }
func SecretResponse(w http.ResponseWriter) http.ResponseWriter { func SecretResponse(w http.ResponseWriter) http.ResponseWriter {
return &secretResponse{w} return &secretResponse{w}
} }
type secretResponse struct {
http.ResponseWriter
}
func (s *secretResponse) Write(b []byte) (int, error) {
return SecretWrite(s.ResponseWriter, string(b))
}