yegor256/judges

`Judges::Judges#fits?` doesn't escape regex metacharacters, so `--boost`/`--demote` patterns over-match

Offen

#476 geöffnet am 12.07.2026

 (2 Kommentare) (0 Reaktionen) (0 zugewiesene Personen)Ruby (15 Forks)github user discovery
bughelp wanted

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('*', '.*').

Contributor Guide