Skip to content

Potential Bug in Rack-Attack Gem with Ruby on Rails #668

@dadiaz18

Description

@dadiaz18

Gem Versions:

  • rack-attack: 6.7.0
  • ruby: 3.3.4
  • rails: 7.0.8.4
  • redis 4.8.1

Context

I encountered an issue with the rack-attack gem when applied to a Rails application. I noticed that the TTL (Time-to-Live) values for Redis keys are inconsistently applied, causing problems with request rate limiting.

Problem Description

When blocking requests based on actions taken on an endpoint, the filters apply a TTL in Redis that does not align with the expected duration. This inconsistency happens randomly. For instance, if a 3-minute window is supposed to validate more than 20 hits, the Redis key should have a TTL of approximately 180 seconds. However, in some cases, it only applies a TTL of 80 seconds, making it impossible to validate the conditions because the data persists incorrectly.

This issue is not noticeable with smaller numbers of hits in a shorter time frame (e.g., 10 hits in one minute) because the TTL mismatch is less obvious. For example, the expected TTL might be 60 seconds, but it sometimes applies 30 seconds, thus obscuring the error.

Example code for implementation

RA_REDIS_CONF = {
  url: ENV.fetch("REDIS_URL"),
  ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE },
}

rack_attack = Rack::Attack
rack_attack.cache.store = ActiveSupport::Cache::RedisCacheStore.new(**RA_REDIS_CONF)

API_ENDPOINT = "/api/endpoint"

rack_attack.blocklist("filter 1") do |req|
  rack_attack::Allow2Ban.filter("filter_1:#{req.ip}", maxretry: 20, findtime: 180, bantime: 1.hour) do
    req.path == API_ENDPOINT && req.post?
  end
end

rack_attack.blocklist("filter 2") do |req|
  rack_attack::Allow2Ban.filter("filter_2:#{req.ip}", maxretry: 10, findtime: 60, bantime: 3.minutes) do
    req.path == API_ENDPOINT && req.post?
  end
end

rack_attack.blocklisted_responder = lambda do |request_env|
  [403, { "Content-Type" => "application/json" }, [{ error: "Too many requests. Please try again later." }.to_json]]
end

Logs of TTLs wrongly applied when I start the counters

TTL for rack::attack:95485:allow2ban:count:filter_1:14.0.4.4: --> 68  # (should be approx 180)
TTL for rack::attack:25841:allow2ban:count:filter_2:14.0.4.4: --> 33  # (should be approx 60)

Please, any possible solution related to this?

Thanks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions