fix(mail): prevent ReDoS in Search by escaping user input

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 <noreply@anthropic.com>
This commit is contained in:
gastown/crew/joe
2026-01-04 23:53:19 -08:00
committed by Steve Yegge
parent 254288800d
commit 2c6654b5b2

View File

@@ -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)
}