GuardAPI Logo
GuardAPI

Fix NoSQL Injection in Hanami

NoSQL Injection in Hanami typically manifests when raw, unsanitized parameters are passed directly into the underlying persistence layer (usually ROM with a MongoDB adapter or Mongoid). Attackers exploit this by submitting hash-based operators like {'$gt': ''} to bypass authentication or extract unauthorized data. As a Senior AppSec Researcher, I've seen this most often in Hanami applications that neglect strict parameter validation in the Action layer.

The Vulnerable Pattern

class Web::Actions::Sessions::Create < Web::Action
  def handle(req, res)
    # VULNERABLE: Directly passing a hash from params to the repository
    # If req.params[:user] is { "password": { "$gt": "" } }, the query bypasses the check.
    user = UserRepository.new.find_by_credentials(req.params[:user])
    if user
      res.session[:user_id] = user.id
      res.redirect_to '/dashboard'
    end
  end
end

repository/user_repository.rb

def find_by_credentials(criteria) users.where(criteria).one end

The Secure Implementation

The fix relies on two defensive layers: 1. Strict Schema Validation: By using Hanami::Action's built-in dry-validation integration, we force the input to be a specific type (String). If an attacker passes a hash object, validation fails before the database is even touched. 2. Explicit Repository Mapping: Never pass a raw hash into a 'where' clause. By deconstructing the hash and explicitly casting values to strings (.to_s), we neutralize MongoDB/NoSQL operators, ensuring the database treats the input as a literal search term rather than a query directive.

class Web::Actions::Sessions::Create < Web::Action
  params do
    required(:user).hash do
      required(:email).filled(:string)
      required(:password).filled(:string)
    end
  end

def handle(req, res) halt 422 unless req.params.valid?

# SECURE: Pass specific, validated scalar values to the repository
user = UserRepository.new.find_by_credentials(
  email: req.params[:user][:email],
  password: req.params[:user][:password]
)
# ... handle session

end end

repository/user_repository.rb

def find_by_credentials(email:, password:)

SECURE: Explicitly binding values to keys ensures NoSQL operators are treated as strings

users.where(email: email.to_s, password: password.to_s).one end

System Alert • ID: 8221
Target: Hanami API
Potential Vulnerability

Your Hanami API might be exposed to NoSQL Injection

74% of Hanami apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

Free Tier • No Credit Card • Instant Report

Verified by Ghost Labs Security Team

This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.