HIGH mass assignmentgrape

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
end

This 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 params object contains all request parameters, including those not explicitly declared in the params do block
  • 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
end

When 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
end

Attribute 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 IDNameSeverity
CWE-915Mass Assignment HIGH

Frequently Asked Questions

How does middleBrick detect mass assignment vulnerabilities in Grape APIs?
middleBrick analyzes Grape endpoint definitions to identify parameters that flow directly to model operations without filtering. It traces parameter usage through the code, flags endpoints using patterns like 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?
Unlike Rails, Grape doesn't enforce strong parameters by default. The 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.