From e21f7313c8ccf65b5726b45cbf05f5c10942f6b6 Mon Sep 17 00:00:00 2001 From: chen21019 Date: Wed, 26 Aug 2026 14:42:31 +0800 Subject: [PATCH] security: sanitize external event log fields --- internal/events/safe_log.go | 12 ++++++++++++ internal/events/safe_log_test.go | 9 +++++++++ internal/events/worker.go | 25 ++++++++++++++++--------- 3 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 internal/events/safe_log.go create mode 100644 internal/events/safe_log_test.go diff --git a/internal/events/safe_log.go b/internal/events/safe_log.go new file mode 100644 index 00000000..edfb6ee7 --- /dev/null +++ b/internal/events/safe_log.go @@ -0,0 +1,12 @@ +package events + +import ( + "fmt" + "strings" +) + +func safeLogValue(value interface{}) string { + text := fmt.Sprint(value) + text = strings.ReplaceAll(text, "\r", "") + return strings.ReplaceAll(text, "\n", " ") +} diff --git a/internal/events/safe_log_test.go b/internal/events/safe_log_test.go new file mode 100644 index 00000000..463decc7 --- /dev/null +++ b/internal/events/safe_log_test.go @@ -0,0 +1,9 @@ +package events + +import "testing" + +func TestSafeLogValueProducesSingleRecord(t *testing.T) { + if got := safeLogValue("first\r\nforged\nthird"); got != "first forged third" { + t.Fatalf("unexpected safe log value: %q", got) + } +} diff --git a/internal/events/worker.go b/internal/events/worker.go index 59601d57..1d1bde31 100644 --- a/internal/events/worker.go +++ b/internal/events/worker.go @@ -47,7 +47,12 @@ func (wp *skippingWorkerPool) HandleWork(event *Event, eventHandlers map[string] doWork(event, eventHandlers, apiClient, wp.eventLocker(event)) }() default: - log.Warnf("No workers available, dropping event. workerCount: %v, event: %v", cap(wp.workers), *event) + log.WithFields(log.Fields{ + "workerCount": cap(wp.workers), + "eventName": safeLogValue(event.Name), + "eventId": safeLogValue(event.ID), + "resourceId": safeLogValue(event.ResourceID), + }).Warn("No workers available; dropping event") } } @@ -77,14 +82,16 @@ func doWork(event *Event, eventHandlers map[string]EventHandler, apiClient *clie if event.Name != "ping" { log.WithFields(log.Fields{ - "event": *event, + "eventName": safeLogValue(event.Name), + "eventId": safeLogValue(event.ID), + "resourceId": safeLogValue(event.ResourceID), }).Debug("Processing event.") } unlocker := locker.Lock() if unlocker == nil { log.WithFields(log.Fields{ - "resourceId": event.ResourceID, + "resourceId": safeLogValue(event.ResourceID), }).Debug("Resource locked. Dropping event") return } @@ -93,10 +100,10 @@ func doWork(event *Event, eventHandlers map[string]EventHandler, apiClient *clie if fn, ok := eventHandlers[event.Name]; ok { if err := fn(event, apiClient); err != nil { log.WithFields(log.Fields{ - "eventName": event.Name, - "eventId": event.ID, - "resourceId": event.ResourceID, - "err": err, + "eventName": safeLogValue(event.Name), + "eventId": safeLogValue(event.ID), + "resourceId": safeLogValue(event.ResourceID), + "err": safeLogValue(err), }).Error("Error processing event") reply := &client.Publish{ @@ -108,13 +115,13 @@ func doWork(event *Event, eventHandlers map[string]EventHandler, apiClient *clie _, err := apiClient.Publish.Create(reply) if err != nil { log.WithFields(log.Fields{ - "err": err, + "err": safeLogValue(err), }).Error("Error sending error-reply") } } } else { log.WithFields(log.Fields{ - "eventName": event.Name, + "eventName": safeLogValue(event.Name), }).Warn("No event handler registered for event") } }