`Judges::Judges#fits?` doesn't escape regex metacharacters, so `--boost`/`--demote` patterns over-match
#476 geöffnet am 12.07.2026
Repository-Metriken
- Stars
- (7 Sterne)
- PR-Merge-Metriken
- (PR-Metriken ausstehend)
Beschreibung
Judges::Judges#fits? (lib/judges/judges.rb:137-142), used to match judge names against --boost/--demote patterns, only translates * to .* before building the match regex:
def fits?(name, patterns)
return false if patterns.nil? || patterns.empty?
Array(patterns).any? do |pattern|
name.match?("\\A#{pattern.gsub('*', '.*')}\\z")
end
end
Every other regex metacharacter in the user-supplied pattern (., +, ?, (, ), [, ], etc.) is passed straight into the regex unescaped. Per the feature's own originating issue (#344, closed), the intended semantics are: "* means .* (regexp) and that's it" — i.e. everything besides * should match literally.
What happens: a pattern containing a literal dot, e.g. --demote=my.judge, is meant to match only the exact judge name my.judge. Because the dot is interpreted as a regex "any character," it also matches unrelated judge names that merely happen to have some other character in that position:
fits?("myXjudge", ["my.judge"]) # => true (WRONG — should be false)
fits?("my.judge", ["my.judge"]) # => true (correct)
Judge names containing dots are common (many real judges are named like some.judge or reference dotted paths), so this isn't a corner case — any such pattern silently over-matches.
Impact: --boost/--demote can silently reorder judges that were never intended to match the given pattern, whenever the pattern contains any regex metacharacter other than *.
What should happen: all characters in the pattern except * should be treated literally, e.g. Regexp.escape(pattern).gsub('\*', '.*') instead of the current bare pattern.gsub('*', '.*').