HIGH insecure designhanamiruby

Insecure Design in Hanami (Ruby)

Insecure Design in Hanami with Ruby — how this specific combination creates or exposes the vulnerability

Insecure design in Hanami applications written in Ruby often stems from architectural decisions that prioritize convenience over least-privilege and explicit authorization. Hanami encourages a rich domain model with entities and repositories, but if authorization checks are omitted at the use-case or entity level, endpoints can expose functionality that should be restricted. For example, a use-case that updates a resource might infer the resource identifier from user-supplied JSON and operate without verifying that the current subject has rights to that specific identifier, effectively creating a BOLA/IDOR condition.

Ruby’s metaprogramming and flexible public/protected/private semantics can inadvertently contribute to insecure design if developers rely on method visibility alone for access control. In Hanami, service objects or interactors that are public by default may be invoked from controllers without proper guards. Consider a Hanami action that accepts an :id parameter and loads an object via a repository method without scope restriction:

module Web::Controllers::Accounts
  class Update
    include Hanami::Action

    def call(params)
      account = AccountRepository.new.find(params[:id])
      # No check whether current_user can manage this account
      AccountUpdateService.new.call(account, params)
    end
  end
end

If the repository’s find returns any record the user can technically reach (e.g., by ID iteration or guessing), and there is no per-instance authorization, this design exposes BOLA/IDOR. Similarly, Property Authorization issues arise when a form or JSON schema allows mass-assignable attributes that the backend should never permit to be set by the client (such as role or admin). In Hanami, using Entity#attributes for updates without a strict whitelist can lead to privilege escalation.

Input validation weaknesses are another facet of insecure design in this stack. Hanami encourages using validators, but if validations are split or inconsistent between API and UI layers, an attacker can supply crafted payloads that bypass checks. For instance, relying solely on client-side validation or incomplete server-side contracts can open the door to injection or business logic flaws. The combination of Ruby’s dynamic nature and Hanami’s emphasis on composable objects can make it harder to maintain a single source of truth for validation rules across endpoints.

Rate limiting and Data Exposure are also design concerns. If Hanami apps do not enforce request throttling at the use-case or gateway level, and if sensitive data is returned in API responses without field-level filtering, the architecture itself enables excessive data leakage. Encryption misdesign surfaces when secrets or session tokens are handled with weak defaults in Ruby libraries or when transport protections are assumed to be sufficient without additional safeguards. SSRF risks appear if the app accepts URLs or file paths from users and passes them to external services without strict allowlists, and Inventory Management issues occur when internal components or gem versions are exposed through debug endpoints or error messages.

Lastly, Unsafe Consumption and LLM/AI Security considerations tie into insecure design: endpoints that accept unstructured input and forward it to downstream services or AI features can propagate malicious content. In Hanami, if user input is passed directly to prompt templates or external calls without canonicalization and strict schema checks, the design fails to contain abuse surfaces. The framework does not automatically mitigate these risks; they must be addressed deliberately in architecture and code reviews.

Ruby-Specific Remediation in Hanami — concrete code fixes

Remediation in Hanami with Ruby centers on explicit, scoped authorization, strict input contracts, and consistent validation. Use Hanami’s built-in patterns such as Authorizable modules or custom policy objects to enforce per-instance checks. For BOLA/IDOR, ensure that every repository lookup is constrained by the current user’s scope rather than trusting the client-supplied identifier alone:

module Web::Controllers::Accounts
  class Update
    include Hanami::Action

    def call(params)
      account = AccountRepository.new.by_user(current_user.id).find(params[:id])
      return halt 403 unless account
      AccountUpdateService.new.call(account, account_params(params))
    end

    private

    def account_params(params)
      params.slice(:name, :email)
    end
  end
end

This ensures that the repository method by_user scopes records to the current user, eliminating trivial ID guessing attacks. For Property Authorization, define a strict permit list for mass assignment and apply it in the entity or service layer:

class AccountEntity
  include Hanami::Entity

  attributes :id, :name, :email

  def update(params)
    permitted = params.slice(:name, :email)
    # Explicitly reject role, admin, or other sensitive fields
    self.class.new(permitted).to_h
  end
end

Input validation should be centralized using Hanami’s validators to avoid split logic:

class CreateAccountContract
  include Hanami::Validations::Contract

  params do
    required(:name).filled(:str?, size?: 1..100)
    required(:email).filled(:str?, format?: Hanami::Utils::EMAIL_REGEX)
  end
end

Use this contract in your action to reject malformed or malicious payloads early:

class CreateAccount
  include Hanami::Action

  def call(params)
    result = CreateAccountContract.new.call(params)
    result.success? ? proceed(result) : halt(422, result.errors.to_h)
  end
end

To address Rate Limiting, implement a lightweight strategy at the action or gateway level, and for Data Exposure, filter sensitive fields in entities or use view models that exclude secrets:

class SafeAccountEntity
  include Hanami::Entity

  attributes :id, :name
  # Deliberately omit email, role, tokens
end

For Encryption and SSRF, avoid embedding secrets in client-side artifacts and validate any user-provided URLs against a strict allowlist before making outbound calls. Use dependency injection in Hanami to substitute safe clients in tests and production. For Inventory Management, pin gem versions via a lockfile and avoid exposing debug routes or versions in error pages. These Ruby-specific practices, combined with regular security scans using tools like middleBrick, help maintain a robust Hanami architecture.

Frequently Asked Questions

How does Hanami’s use of Ruby increase the risk of BOLA/IDOR if authorization is not explicit?
Hanami’s Ruby-based design encourages rich domain models and public use cases. If developers do not enforce per-instance authorization—e.g., scoping repository queries to the current user—an attacker can iterate or guess IDs to access other users’ resources, leading to BOLA/IDOR.
Why is a strict permit list for mass assignment important in Hanami entities written in Ruby?
Because Ruby allows flexible hash manipulation, Hanami entities can inadvertently accept attributes like role or admin if mass assignment is not restricted. A strict permit list in the entity or contract ensures only intended fields are updated, preventing privilege escalation via property authorization flaws.