From 8fc36a4f9bdd4ea1c9784d2570102a5a1d16dd57 Mon Sep 17 00:00:00 2001 From: Dmitrii Balabanov Date: Fri, 13 Mar 2026 12:06:48 +0200 Subject: [PATCH 1/2] fix(logger): mask bot tokens in 3rd-party logger output --- pkg/logger/logger_3rd_party.go | 36 ++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/pkg/logger/logger_3rd_party.go b/pkg/logger/logger_3rd_party.go index da50d686a..3c311520c 100644 --- a/pkg/logger/logger_3rd_party.go +++ b/pkg/logger/logger_3rd_party.go @@ -2,7 +2,19 @@ package logger -import "fmt" +import ( + "fmt" + "regexp" +) + +// botTokenRe matches the secret part of a Telegram bot token embedded in a URL +// or log message: /bot:/ → /bot:****/ +var botTokenRe = regexp.MustCompile(`(bot\d+:)[A-Za-z0-9_-]{20,}`) + +// maskSecrets replaces any embedded bot tokens in s with a redacted placeholder. +func maskSecrets(s string) string { + return botTokenRe.ReplaceAllString(s, "${1}****") +} // Logger implements common Logger interface type Logger struct { @@ -12,52 +24,52 @@ type Logger struct { // Debug logs debug messages func (b *Logger) Debug(v ...any) { - logMessage(DEBUG, b.component, fmt.Sprint(v...), nil) + logMessage(DEBUG, b.component, maskSecrets(fmt.Sprint(v...)), nil) } // Info logs info messages func (b *Logger) Info(v ...any) { - logMessage(INFO, b.component, fmt.Sprint(v...), nil) + logMessage(INFO, b.component, maskSecrets(fmt.Sprint(v...)), nil) } // Warn logs warning messages func (b *Logger) Warn(v ...any) { - logMessage(WARN, b.component, fmt.Sprint(v...), nil) + logMessage(WARN, b.component, maskSecrets(fmt.Sprint(v...)), nil) } // Error logs error messages func (b *Logger) Error(v ...any) { - logMessage(ERROR, b.component, fmt.Sprint(v...), nil) + logMessage(ERROR, b.component, maskSecrets(fmt.Sprint(v...)), nil) } // Debugf logs formatted debug messages func (b *Logger) Debugf(format string, v ...any) { - logMessage(DEBUG, b.component, fmt.Sprintf(format, v...), nil) + logMessage(DEBUG, b.component, maskSecrets(fmt.Sprintf(format, v...)), nil) } // Infof logs formatted info messages func (b *Logger) Infof(format string, v ...any) { - logMessage(INFO, b.component, fmt.Sprintf(format, v...), nil) + logMessage(INFO, b.component, maskSecrets(fmt.Sprintf(format, v...)), nil) } // Warnf logs formatted warning messages func (b *Logger) Warnf(format string, v ...any) { - logMessage(WARN, b.component, fmt.Sprintf(format, v...), nil) + logMessage(WARN, b.component, maskSecrets(fmt.Sprintf(format, v...)), nil) } // Warningf logs formatted warning messages func (b *Logger) Warningf(format string, v ...any) { - logMessage(WARN, b.component, fmt.Sprintf(format, v...), nil) + logMessage(WARN, b.component, maskSecrets(fmt.Sprintf(format, v...)), nil) } // Errorf logs formatted error messages func (b *Logger) Errorf(format string, v ...any) { - logMessage(ERROR, b.component, fmt.Sprintf(format, v...), nil) + logMessage(ERROR, b.component, maskSecrets(fmt.Sprintf(format, v...)), nil) } // Fatalf logs formatted fatal messages and exits func (b *Logger) Fatalf(format string, v ...any) { - logMessage(FATAL, b.component, fmt.Sprintf(format, v...), nil) + logMessage(FATAL, b.component, maskSecrets(fmt.Sprintf(format, v...)), nil) } // Log logs a message at a given level with caller information @@ -75,7 +87,7 @@ func (b *Logger) Log(msgL, caller int, format string, a ...any) { level = lvl } } - logMessage(level, b.component, fmt.Sprintf(format, a...), nil) + logMessage(level, b.component, maskSecrets(fmt.Sprintf(format, a...)), nil) } // Sync flushes log buffer (no-op for this implementation) From 64ceb5ab760703b0b27e933f1a022f7b64de64aa Mon Sep 17 00:00:00 2001 From: Dmitrii Balabanov Date: Fri, 13 Mar 2026 12:09:03 +0200 Subject: [PATCH 2/2] fix(logger): show first/last 4 chars of bot token for identification --- pkg/logger/logger_3rd_party.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pkg/logger/logger_3rd_party.go b/pkg/logger/logger_3rd_party.go index 3c311520c..d0cb178c5 100644 --- a/pkg/logger/logger_3rd_party.go +++ b/pkg/logger/logger_3rd_party.go @@ -7,13 +7,14 @@ import ( "regexp" ) -// botTokenRe matches the secret part of a Telegram bot token embedded in a URL -// or log message: /bot:/ → /bot:****/ -var botTokenRe = regexp.MustCompile(`(bot\d+:)[A-Za-z0-9_-]{20,}`) +// botTokenRe matches the bot ID prefix and the secret part of a Telegram bot token. +// Groups: 1 = "bot:", 2 = first 4 chars of secret, 3 = middle, 4 = last 4 chars. +var botTokenRe = regexp.MustCompile(`(bot\d+:)([A-Za-z0-9_-]{4})[A-Za-z0-9_-]{12,}([A-Za-z0-9_-]{4})`) -// maskSecrets replaces any embedded bot tokens in s with a redacted placeholder. +// maskSecrets replaces any embedded bot tokens in s with a redacted placeholder +// that keeps the first and last 4 characters of the secret for identification. func maskSecrets(s string) string { - return botTokenRe.ReplaceAllString(s, "${1}****") + return botTokenRe.ReplaceAllString(s, "${1}${2}****${3}") } // Logger implements common Logger interface