Loading lib/labkit/rate_limit/matcher.rb +9 −3 Original line number Diff line number Diff line Loading @@ -37,10 +37,16 @@ module Labkit # MAX_REGEX_SOURCE_LENGTH bounds the pattern, not the match: short # patterns can still backtrack badly. This bounds the match. # # 5ms is ~10,000x the slowest realistic match measured against # GitLab-style route patterns (worst observed: 0.0005ms), so a # legitimate rule cannot trip it even on a loaded box, while a # Measured against GitLab's real RackAttack path patterns # (API_PATH_REGEX, WEB_PATH_REGEX, Packages::API_PATH_REGEX and the # health/internal/registry/collector patterns) on inputs up to 16KB, # including many-segment and newline-heavy paths: worst observed match # 0.0419ms, none timed out. 5ms is therefore ~119x the slowest real # match - enough that a legitimate rule will not trip it, while a # pathological one is capped well below a request budget. # # None of those patterns use nested quantifiers or backreferences, so # none can backtrack exponentially; re-measure if that changes. MATCH_TIMEOUT_SECONDS = 0.005 def self.build(input) Loading Loading
lib/labkit/rate_limit/matcher.rb +9 −3 Original line number Diff line number Diff line Loading @@ -37,10 +37,16 @@ module Labkit # MAX_REGEX_SOURCE_LENGTH bounds the pattern, not the match: short # patterns can still backtrack badly. This bounds the match. # # 5ms is ~10,000x the slowest realistic match measured against # GitLab-style route patterns (worst observed: 0.0005ms), so a # legitimate rule cannot trip it even on a loaded box, while a # Measured against GitLab's real RackAttack path patterns # (API_PATH_REGEX, WEB_PATH_REGEX, Packages::API_PATH_REGEX and the # health/internal/registry/collector patterns) on inputs up to 16KB, # including many-segment and newline-heavy paths: worst observed match # 0.0419ms, none timed out. 5ms is therefore ~119x the slowest real # match - enough that a legitimate rule will not trip it, while a # pathological one is capped well below a request budget. # # None of those patterns use nested quantifiers or backreferences, so # none can backtrack exponentially; re-measure if that changes. MATCH_TIMEOUT_SECONDS = 0.005 def self.build(input) Loading