HIGH api rate abusehanamifirestore

Api Rate Abuse in Hanami with Firestore

Api Rate Abuse in Hanami with Firestore — how this specific combination creates or exposes the vulnerability

Rate abuse in a Hanami application that uses Google Cloud Firestore arises because Firestore’s serverless nature and per-project request quotas can be exhausted by uncontrolled client behavior. Hanami, a Ruby web framework, does not impose application-level rate limits by default, and Firestore does not natively enforce per-user or per-API-key rate limits at the database tier for read/write operations. This gap allows a single client or bot to generate a high volume of requests that translate into repeated Firestore document reads and writes, quickly consuming available quota and triggering project-level throttling or denial of service.

In a typical Hanami service, API endpoints interact with Firestore via the google-cloud-firestore Ruby client. Each HTTP request from an unauthenticated or weakly authenticated user can trigger multiple Firestore operations—for example, reading a document to fetch configuration, writing a log entry, and updating a usage counter. Without rate limiting, an attacker can script rapid calls to these endpoints, causing write amplification (such as incrementing counters or creating records) and read storms that increase latency and cost. Because Firestore operations are billed and quota-limited at the project level, this abuse can inflate costs and degrade performance for legitimate users.

The risk is compounded when endpoints expose Firestore document IDs derived from user input without validation. For instance, an endpoint like GET /widgets/:id that directly uses params[:id] to form a Firestore path allows an attacker to probe document namespaces rapidly. Additionally, Firestore’s real-time capabilities and snapshot listeners can be leveraged to sustain long-polling connections, further intensifying request volume. Without complementary controls—such as token-bucket rate limiters, API keys with quota restrictions, or middleware to track request frequencies—an attacker can trigger OWASP API Top 10:2023 Broken Object Level Authorization (BOLA) and excessive resource consumption patterns that align with common attack vectors like IDOR when object references are predictable.

Because middleBrick scans the unauthenticated attack surface, it can detect endpoints that show signs of missing rate controls and map them to the Rate Limiting check, assigning severity based on observable behavior such as rapid repeated responses or absence of throttling headers. The scan also highlights whether Firestore-related endpoints are exposed without authentication, which is relevant to the Authentication and BFLA checks. These findings provide remediation guidance, including implementing per-endpoint rate limits and validating input before constructing Firestore queries.

Firestore-Specific Remediation in Hanami

To mitigate rate abuse in Hanami with Firestore, implement application-level throttling combined with Firestore-side safeguards. In Hanami, you can use middleware or a lightweight rate-limiting library to track requests per identity (API key, IP, or user ID) and enforce ceilings before invoking Firestore operations. Below are concrete code examples that demonstrate how to integrate rate limiting and input validation within a Hanami endpoint that reads and writes Firestore data.

First, add a rate-limiting gem such as rack-attack to your Gemfile and configure it to limit requests per minute for Firestore-related routes. This ensures that abusive clients are throttled before reaching your Hanami actions.

# config/initializers/rack_attack.rb
class Rack::Attack
  # Throttle all requests to /api/widgets by IP address
  throttle("api/ip", limit: 30, period: 60) do |req|
    req.ip if req.path.start_with?("/api/widgets")
  end

  # Block offending IPs and return a 429 response
  self.throttled_response = lambda do |env|
    [429, {}, ["Rate limit exceeded. Try again later.\n"]]
  end
end

Second, validate and sanitize inputs before constructing Firestore paths. Avoid directly using user-provided IDs to form document references. Instead, map them to known, safe collections and enforce allowlists where possible.

# app/actions/widgets/show.rb
module Actions
  class Widgets::Show
    include Hanami::Action

    def initialize(firestore_client)
      @firestore = firestore_client
    end

    def call(params)
      # Validate ID format to prevent enumeration attacks
      widget_id = params[:id]
      unless widget_id.match?(Regexp.union(/\A[a-z0-9_-]{1,64}\z/))
        self.status = 400
        return { error: "invalid_id" }
      end

      # Safe document reference
      doc_ref = @firestore.doc("widgets_public/#{widget_id}")
      snapshot = doc_ref.get

      if snapshot.exists?
        { widget: snapshot.data }
      else
        self.status = 404
        { error: "not_found" }
      end
    end
  end
end

Third, when writing data, use Firestore transactions or batched writes with uniqueness constraints to prevent duplicate creation from retries, and apply per-user quotas by storing usage counters in a separate document with atomic increments.

# app/actions/widgets/create.rb
module Actions
  class Widgets::Create
    include Hanami::Action

    def initialize(firestore_client)
      @firestore = firestore_client
    end

    def call(params)
      user_id = params[:user_id]
      # Enforce a per-user creation limit using a counter document
      counter_ref = @firestore.doc("quotas/#{user_id}")
      @firestore.run_transaction do |transaction|
        counter = transaction.get(counter_ref)
        current = counter.exists? ? counter[:count] || 0 : 0
        if current >= 100
          self.status = 429
          return { error: "quota_exceeded" }
        end
        transaction.update(counter_ref, { count: current + 1 })
        # Proceed to create the widget document
        widget_ref = @firestore.doc("widgets/#{SecureRandom.uuid}")
        transaction.create(widget_ref, params.to_h)
        { id: widget_ref.id }
      end
    rescue Google::Cloud::Aborted => e
      self.status = 500
      { error: "transaction_conflict", details: e.message }
    end
  end
end

These measures—combined with monitoring of Firestore quota usage and alerts on unusual patterns—reduce the likelihood of rate abuse. middleBrick’s scans can verify the presence of these controls by checking response headers for rate-limiting indicators and testing for excessive responses without throttling.

Frequently Asked Questions

Can Firestore client-side quotas replace server-side rate limiting in Hanami?
No. Client-side quotas are easily bypassed in unauthenticated or compromised scenarios. Server-side rate limiting in Hanami, enforced via middleware such as rack-attack and validated before Firestore operations, is required to prevent API rate abuse.
How does middleBrick assess rate limiting for Firestore-backed Hanami APIs?
middleBrick executes the Rate Limiting check by sending repeated requests to endpoints and observing whether responses are throttled. It also examines authentication and authorization coverage to identify BOLA/IDOR risks that can be combined with rate abuse to escalate impact.