GuardAPI Logo
GuardAPI

Fix NoSQL Injection in Roda

NoSQL injection in Roda applications occurs when raw Rack parameters are passed directly into database query filters. Because Rack parses nested parameters into Ruby Hashes, an attacker can supply operators like $gt, $ne, or $regex. If your application logic expects a string but receives a hash, the MongoDB driver will execute the operator, leading to authentication bypass or data exfiltration. In a Roda context, trusting r.params without explicit type casting is a critical failure.

The Vulnerable Pattern

class App < Roda
  route do |r|
    r.post "search" do
      # VULNERABLE: Direct injection of the params hash into the MongoDB query.
      # If r.params['id'] is {"$ne": null}, it returns all records.
      record = DB[:items].find(_id: r.params['id']).first
      record.to_json
    end
r.post "login" do
  # VULNERABLE: Attacker sends pass[$ne]=wrong_password to bypass auth.
  user = DB[:users].find(user: r.params['user'], pass: r.params['pass']).first
  user ? "Welcome" : "Denied"
end

end end

The Secure Implementation

The root cause is the mismatch between the application's expected input type (String) and the NoSQL driver's ability to process complex types (Hash). When an attacker sends a request with 'pass[$ne]=1', Rack parses this into {'pass' => {'$ne' => '1'}}. Passing this hash directly into a MongoDB 'find' call triggers the 'not equal' operator. The defense-in-depth approach for Roda developers is to always cast user-controlled inputs using .to_s or .to_i. For complex applications, utilizing a validation layer like Dry-Validation or Mongoid's internal type casting is recommended to ensure that parameters conform to a strict schema before reaching the database layer.

class App < Roda
  route do |r|
    r.post "search" do
      # SECURE: Explicitly cast input to String to neutralize NoSQL operators.
      # This forces the driver to treat the input as a literal value.
      search_id = r.params['id'].to_s
  record = DB[:items].find(_id: search_id).first
  record.to_json
end

r.post "login" do
  # SECURE: Using strict type enforcement via casting.
  username = r.params['user'].to_s
  password = r.params['pass'].to_s

  user = DB[:users].find(user: username, pass: password).first
  user ? "Welcome" : "Denied"
end

end end

System Alert • ID: 8159
Target: Roda API
Potential Vulnerability

Your Roda API might be exposed to NoSQL Injection

74% of Roda 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.