Excessive Data Exposure in Grape with Firestore
Excessive Data Exposure in Grape with Firestore — how this specific combination creates or exposes the vulnerability
Excessive Data Exposure occurs when an API returns more data than necessary for a given operation, often including sensitive fields that should remain restricted. In a Grape API backed by Firestore, this commonly arises when a single endpoint retrieves a full document without explicitly limiting which fields are returned or enforced for the caller’s permissions.
Firestore documents often store a mix of public and sensitive fields—such as email, role, internal_id, or PII—within a single collection. If a Grape resource maps directly to a Firestore document and returns the entire snapshot, clients receive all fields regardless of whether they are needed for the operation. This violates the principle of least privilege and can inadvertently expose administrative flags, internal references, or other data not intended for the client.
The risk is compounded when Firestore security rules are misconfigured or bypassed during development, and the Grape endpoint does not enforce field-level filtering. An attacker may leverage unauthenticated or weakly authenticated endpoints to harvest sensitive information across many records. Because Grape routes often serialize ActiveModel or plain Ruby objects, developers may inadvertently include all attributes without considering which should be exposed.
middleBrick detects this category under its Data Exposure checks, specifically analyzing how endpoints map to Firestore documents and whether responses include unnecessary fields. The scanner compares the OpenAPI contract with runtime behavior, flagging responses that contain high-risk fields such as password_digest, auth_token, or firebase_uid without appropriate masking or filtering.
For example, consider a GET /users/:id endpoint that retrieves a Firestore user document. If the route returns the full document—including fields like reset_password_token or internal_admin—it increases the attack surface. middleBrick would flag this as an Excessive Data Exposure finding, noting that the response should be limited to only the fields required by the client, and that sensitive fields must be omitted or transformed based on the requester’s authorization context.
Firestore-Specific Remediation in Grape — concrete code fixes
To remediate Excessive Data Exposure when using Firestore with Grape, explicitly control which fields are serialized and returned. Use projection queries to limit retrieved fields at the database level, and apply attribute filtering before serialization.
Below are concrete code examples showing insecure and secure implementations.
Insecure Example
This Grape endpoint retrieves an entire Firestore document and maps all fields to the response, exposing sensitive data.
class UserResource < Grape::Entity
expose :id, :email, :name, :role, :internal_id, :reset_password_token, :admin
end
class UsersEndpoint < Grape::API
resource :users do
get ':id' do
doc = Firestore::Document.new("users/#{params[:id]}").get
present doc.data, with: UserResource
end
In this example, fields such as reset_password_token and admin are included in the response, which may be unnecessary and risky for general clients.
Secure Example with Field Projection and Filtering
Use Firestore’s select to limit returned fields, and conditionally expose data based on the current user’s permissions.
class PublicUserResource < Grape::Entity
expose :id
expose :email
expose :name
end
class AdminUserResource < Grape::Entity
expose :id
expose :email
expose :name
expose :role
expose :internal_id, if: ->(instance, options) { instance[:admin] == true }
end
class UsersEndpoint < Grape::API
helpers do
def current_user
@current_user ||= authenticate_request!
end
def user_resource_class
if current_user&.admin?
AdminUserResource
else
PublicUserResource
end
end
end
resource :users do
get ':id' do
# Use projection to limit fields at the query level
doc = Firestore::Document.new("users/#{params[:id]}")
.select(:email, :name, :role, :admin, :internal_id)
.get
# Further ensure sensitive fields are not present
filtered_data = doc.data.except("reset_password_token", "password_digest")
present filtered_data, with: user_resource_class
end
end
end
In the secure version, the Firestore query uses select to restrict returned fields, and the response is further filtered to remove any residual sensitive keys. The appropriate entity class is selected based on the requester’s role, ensuring that administrative fields are only exposed when necessary.
middleBrick’s Pro plan supports continuous monitoring and CI/CD integration, which helps ensure that such field exposure issues are caught early and do not reach production without review. Using the GitHub Action, you can fail builds when new endpoints introduce excessive data exposure patterns.
Related CWEs: propertyAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-915 | Mass Assignment | HIGH |