Mass Assignment in Grape
How Mass Assignment Manifests in Grape
Mass assignment vulnerabilities in Grape APIs occur when an endpoint accepts user input that maps directly to model attributes without proper filtering. In Grape applications, this typically manifests through parameter handling in endpoint definitions where developers inadvertently expose sensitive fields to client manipulation.
Consider a Grape API endpoint that updates user profiles:
class API < Grape::API
params do
requires :name, type: String
requires :email, type: String
requires :role, type: String
requires :is_admin, type: Boolean
end
put '/users/:id' do
user = User.find(params[:id])
user.update(params)
present user, with: UserEntity
end
endThis endpoint is vulnerable because user.update(params) attempts to update all attributes from the params hash. An attacker can modify the role field to elevate privileges or set is_admin to true, bypassing authorization controls.
Grape's parameter handling makes this particularly dangerous because:
- The
paramsobject contains all request parameters, including those not explicitly declared in theparams doblock - Strong parameters aren't enforced by default in Grape (unlike Rails)
- Entity definitions don't automatically filter updateable attributes
- Dynamic parameter blocks can inadvertently expose model attributes
Another common pattern involves nested attributes:
params do
optional :user, type: Hash do
requires :name, type: String
requires :email, type: String
requires :password, type: String
requires :role, type: String
end
endWhen this hash is passed directly to User.create or update, attackers can manipulate any field exposed in the parameter structure.
Grape-Specific Detection
Detecting mass assignment vulnerabilities in Grape APIs requires examining how parameters flow from endpoint definitions to model operations. middleBrick's scanning engine specifically targets these Grape patterns:
Parameter Exposure Analysis: The scanner examines Grape endpoint definitions to identify parameters that map directly to model attributes. It flags endpoints where:
- Parameters are declared but not explicitly filtered before model operations
- Nested parameter structures contain sensitive fields
- Dynamic parameter blocks (
optional :user, type: Hash do) are used without validation
Model Operation Tracing: middleBrick traces parameter usage through the endpoint code to identify dangerous patterns like:
user.update(params) # Vulnerable
user.update(params[:user]) # Vulnerable if :user contains sensitive fields
User.create(params) # Vulnerable
Entity Definition Analysis: The scanner checks Grape entities to ensure they don't expose sensitive attributes that could be manipulated through mass assignment. It verifies that entities properly filter attributes for both presentation and update operations.
Runtime Testing: middleBrick actively tests Grape endpoints by submitting requests with modified parameter values for sensitive fields like role, is_admin, permissions, and owner_id. It observes whether the API accepts and processes these unauthorized modifications.
Using middleBrick's CLI for Grape API scanning:
middlebrick scan https://api.example.com/users
The scanner provides a security score and specific findings for mass assignment vulnerabilities, including the exact parameters and endpoints at risk.
Grape-Specific Remediation
Remediating mass assignment vulnerabilities in Grape requires implementing proper parameter filtering and using Grape's built-in security features. Here are effective approaches:
Strong Parameters Pattern: Explicitly filter parameters before model operations:
class API < Grape::API
params do
requires :name, type: String
requires :email, type: String
end
put '/users/:id' do
user = User.find(params[:id])
# Only allow specific attributes
allowed_params = declared(params, include_missing: false).to_hash
allowed_params.slice!(:name, :email)
user.update(allowed_params)
present user, with: UserEntity
end
endAttribute Whitelisting: Use Grape's permit! equivalent by explicitly declaring allowed attributes:
params do
requires :name, type: String
requires :email, type: String
end
put '/users/:id' do
user = User.find(params[:id])
safe_params = params.to_hash.select { |k, _| [:name, :email].include?(k.to_sym) }
user.update(safe_params)
present user, with: UserEntity
end
Entity-Based Filtering: Leverage Grape entities for both presentation and update operations:
class UserUpdateEntity < Grape::Entity
expose :name, :email
# Prevent exposure of sensitive fields
unexpose :role, :is_admin, :password_digest
end
put '/users/:id' do
user = User.find(params[:id])
update_data = UserUpdateEntity.represent(params).serializable_hash
user.update(update_data)
present user, with: UserEntity
end
Model-Level Protection: Combine Grape filtering with ActiveRecord's mass assignment protection:
class User < ApplicationRecord
attr_protected :role, :is_admin, :owner_id
end
# In Grape API
put '/users/:id' do
user = User.find(params[:id])
user.update(params.slice(:name, :email)) # Safe even if params contains protected attrs
present user, with: UserEntity
end
Input Validation: Implement strict type checking and value validation:
params do
requires :name, type: String
requires :email, type: String
requires :age, type: Integer, values: 18..120
end
put '/users/:id' do
user = User.find(params[:id])
safe_params = declared(params, include_missing: false).to_hash
user.update(safe_params)
present user, with: UserEntity
end
These remediation strategies ensure that Grape APIs only accept and process explicitly permitted parameters, eliminating mass assignment vulnerabilities.
Related CWEs: propertyAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-915 | Mass Assignment | HIGH |
Frequently Asked Questions
How does middleBrick detect mass assignment vulnerabilities in Grape APIs?
user.update(params), and actively tests by submitting requests with modified sensitive fields to verify if the API accepts unauthorized attribute changes.What's the difference between Grape's parameter handling and Rails strong parameters?
params object in Grape contains all request parameters, and Grape's declared method only filters for documentation purposes. Developers must explicitly filter parameters before model operations, as Grape won't automatically protect against mass assignment like Rails does with require and permit.