From 5480dee0fd7dd678fa76c3810dd25bb4fe128c4c Mon Sep 17 00:00:00 2001 From: "Brandon McGinty (chatgpt)" Date: Sun, 9 Aug 2026 15:12:29 -0400 Subject: [PATCH] Sanitize names rendered in the channel tree --- client_notification_test.go | 9 +++++++++ ui_tree.go | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/client_notification_test.go b/client_notification_test.go index 0d33cba..762191d 100644 --- a/client_notification_test.go +++ b/client_notification_test.go @@ -55,6 +55,15 @@ func TestNotificationExpansionIsSinglePassAndNotifyDoesNotBlock(t *testing.T) { // Regression: reconnect replaced Stream without destroying the old capture // and renderer resources. Cleanup must be safe for repeated disconnects. +// Regression: user and channel names in the navigation tree bypassed message +// escaping and could still carry terminal control characters. +func TestTreeItemSanitizesServerNames(t *testing.T) { + item := TreeItem{Channel: &gumble.Channel{Name: "\x1b[2Jroom"}} + if got := item.String(); got != "#[2Jroom" { + t.Fatalf("got %q", got) + } +} + func TestCleanupConnectionAudioIsIdempotent(t *testing.T) { b := &Barnard{} b.cleanupConnectionAudio() diff --git a/ui_tree.go b/ui_tree.go index 7469e7b..28c5adc 100644 --- a/ui_tree.go +++ b/ui_tree.go @@ -10,15 +10,15 @@ import ( func (ti TreeItem) String() string { if ti.User != nil { if ti.User.LocallyMuted() { - return "[MUTED] " + ti.User.Name + return "[MUTED] " + esc(ti.User.Name) } // Calculate total volume as percentage boostPercent := float32(ti.User.Boost()-1) * 10 totalVolume := ti.User.Volume()*100 + boostPercent - return fmt.Sprintf("%s [%.0f%%]", ti.User.Name, totalVolume) + return fmt.Sprintf("%s [%.0f%%]", esc(ti.User.Name), totalVolume) } if ti.Channel != nil { - return "#" + ti.Channel.Name + return "#" + esc(ti.Channel.Name) } return "" }