From 2c6654b5b2dfce4bfb4ed2db6f1766f9d7b1444e Mon Sep 17 00:00:00 2001 From: gastown/crew/joe Date: Sun, 4 Jan 2026 23:53:19 -0800 Subject: [PATCH] fix(mail): prevent ReDoS in Search by escaping user input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use regexp.QuoteMeta to treat Query and FromFilter as literal strings instead of raw regex patterns. This prevents ReDoS attacks from malicious patterns and provides more intuitive literal string matching for users. Fixes gt-kwa09 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- internal/mail/mailbox.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/internal/mail/mailbox.go b/internal/mail/mailbox.go index 31dd7463..c1363a36 100644 --- a/internal/mail/mailbox.go +++ b/internal/mail/mailbox.go @@ -640,16 +640,18 @@ type SearchOptions struct { // Search finds messages matching the given criteria. // Returns messages from both inbox and archive. +// Query and FromFilter are treated as literal strings (not regex) to prevent ReDoS. func (m *Mailbox) Search(opts SearchOptions) ([]*Message, error) { - // Compile regex - re, err := regexp.Compile("(?i)" + opts.Query) // Case-insensitive + // Use QuoteMeta to escape special regex chars - prevents ReDoS attacks + // and provides intuitive literal string matching for users + re, err := regexp.Compile("(?i)" + regexp.QuoteMeta(opts.Query)) if err != nil { return nil, fmt.Errorf("invalid search pattern: %w", err) } var fromRe *regexp.Regexp if opts.FromFilter != "" { - fromRe, err = regexp.Compile("(?i)" + opts.FromFilter) + fromRe, err = regexp.Compile("(?i)" + regexp.QuoteMeta(opts.FromFilter)) if err != nil { return nil, fmt.Errorf("invalid from pattern: %w", err) }