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 endrepository/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 enddef 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 sessionend 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
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.
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.