HIGH injection flawsgrapefirestore

Injection Flaws in Grape with Firestore

Injection Flaws in Grape with Firestore — how this specific combination creates or exposes the vulnerability

Grape is a REST-like API micro-framework for Ruby, commonly used to build JSON APIs. When a Grape endpoint accepts client input and uses it to construct Firestore queries, injection flaws can occur if input is not validated or sanitized. Firestore itself does not support traditional SQL-style injection, but injection-like issues arise when untrusted data is used to dynamically build queries, access document fields, or reference collections. For example, using user-controlled values to determine collection names, document IDs, or field keys can lead to Insecure Direct Object Reference (IDOR), BOLA (Broken Level Authorization), or data exposure.

Consider a scenario where a Grape API uses a parameter to specify a Firestore document path:

get '/users/:user_id/profile' do
  user_id = params[:user_id]
  doc_ref = Firestore.get_doc("users/#{user_id}")
  # ...
end

If user_id is not validated, an attacker could supply a path such as ../../../admin/settings to access unrelated documents. This pattern violates BOLA because the authorization check may only confirm that the user can view their own profile, not that the resolved document belongs to them. Firestore security rules can mitigate some risks, but they cannot compensate for an API that exposes internal document paths based on unchecked input.

Another injection risk occurs when field names or map keys are derived from client input. For example:

post '/filter' do
  field = params[:field]
  value = params[:value]
  results = Firestore.collection('products').where(field, '=', value).get
  # ...
end

Passing a dynamic field string into a query can lead to unintended data exposure or bypassed authorization if the field is not strictly enumerated. An attacker might supply __type__ or other internal metadata fields to probe schema or extract information. This aligns with Input Validation and Property Authorization checks, where the API must enforce strict allowlists for field names and ensure that query constraints are applied consistently with authorization logic.

LLM/AI Security checks are relevant here because prompt injection-style probes could be adapted to test whether Firestore-backed endpoints reflect underlying structure in error messages or behavior. For instance, supplying malformed document paths or unexpected data types might cause verbose errors that leak schema details. middleBrick scans for such patterns across its 12 checks, including System Prompt Leakage and Active Prompt Injection testing, to detect insecure handling of dynamic query construction in API endpoints that interact with Firestore.

Additionally, Data Exposure and Encryption checks verify whether sensitive data is unnecessarily included in query results or transmitted without adequate protection. If a Firestore query returns full documents containing API keys or personal information due to over-permissive field selection, the API may violate data minimization principles. middleBrick’s Inventory Management and Unsafe Consumption checks help identify endpoints where document reads are not constrained by required authorization or where response schemas expose more than intended.

Firestore-Specific Remediation in Grape — concrete code fixes

To secure Grape endpoints that interact with Firestore, apply strict input validation, enforce authorization at the document and field level, and avoid dynamic query construction based on client input. Use allowlists for collection and document identifiers, and map user-facing identifiers to internal keys using a controlled lookup mechanism.

Instead of directly interpolating user input into document paths, resolve identifiers through a trusted mapping. For example:

USERS_COLLECTION = 'users'

def current_user_document_path(user_id)
  # Ensure user_id is a valid UUID or integer before use
  raise Grape::Exceptions::NotFound unless user_id.match?(\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\A)
  "#{USERS_COLLECTION}/#{user_id}"
end

get '/profile' do
  document_path = current_user_document_path(current_user.id)
  doc = Firestore.get_doc(document_path)
  # process doc
end

This ensures that user_id conforms to a known format and prevents path traversal or access to arbitrary documents. Authorization should still be verified within Firestore security rules, and the API should not expose internal document paths to the client.

When querying by dynamic field names, use an allowlist to restrict which fields can be used in queries:

ALLOWED_FILTER_FIELDS = %w[name category price stock]

post '/products' do
  field = params[:field]
  raise Grape::Exceptions::BadRequest unless ALLOWED_FILTER_FIELDS.include?(field)

  value = params[:value]
  results = Firestore.collection('products').where(field, '=', value).limit(100).get
  present results.map(&:data)
end

This prevents attackers from probing internal fields or metadata. Combine this with Property Authorization checks to ensure that the requesting user has the right to filter on the specified field.

For document reads that involve user-supplied identifiers, always pair Firestore reads with explicit authorization checks rather than relying on security rules alone. For example:

get '/orders/:order_id' do
  order_id = params[:order_id]
  order_ref = Firestore.collection('orders').doc(order_id)
  order = order_ref.get

  # Ensure the order belongs to the current user
  halt 403 unless order && order[:user_id] == current_user.id

  present order.data
end

This pattern enforces BOLA/IDOR protections at the application layer, ensuring that even if a document ID is guessed or enumerated, access is denied unless the relationship is verified. middleBrick’s BOLA/IDOR and Property Authorization checks validate that such controls are present and consistent across endpoints.

Finally, apply rate limiting and input sanitization to reduce abuse risk. Use Grape’s built-in helpers or integrate with a middleware layer to enforce thresholds. Avoid passing raw user input into Firestore operations that could trigger excessive resource usage. middleBrick’s Rate Limiting and Input Validation checks can detect missing or weak controls, helping teams maintain secure interactions with Firestore-backed APIs.

Frequently Asked Questions

Can Firestore security rules alone prevent injection-like issues in Grape APIs?
Firestore security rules provide an important layer of defense, but they cannot fully prevent injection-like issues when the API itself constructs queries using untrusted input. Rules should complement server-side validation, allowlists, and explicit authorization checks in the application layer.
How does middleBrick detect injection-related risks in APIs that use Firestore?
middleBrick runs checks such as Input Validation, Property Authorization, BOLA/IDOR, and Data Exposure to identify insecure query construction, missing allowlists, excessive document exposure, and improper handling of dynamic fields or paths.