Skip to content

MONGOID-5939 Guard against NoSQL operator injection in where/find_by#6161

Draft
comandeo-mongo wants to merge 1 commit into
mongodb:masterfrom
comandeo-mongo:MONGOID-5939-operator-injection-guard
Draft

MONGOID-5939 Guard against NoSQL operator injection in where/find_by#6161
comandeo-mongo wants to merge 1 commit into
mongodb:masterfrom
comandeo-mongo:MONGOID-5939-operator-injection-guard

Conversation

@comandeo-mongo

@comandeo-mongo comandeo-mongo commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

What

Adds a guard in expr_query that rejects top-level $ operators not in an explicit allowlist when allow_unsafe_query_operators is set to false. The default is true (existing behavior preserved — no BC break).

To opt into the strict mode:

Mongoid.configure do |config|
  config.allow_unsafe_query_operators = false
end

With strict mode on, operators like $where and $function raise Errors::InvalidQuery. Allowed operators: $and, $or, $nor, $not, $text, $comment, $expr, $jsonSchema, $alwaysFalse, $alwaysTrue.

Why

When user-supplied params are passed directly to where/find_by (e.g. via to_unsafe_h), an attacker can inject top-level operators like $where to execute arbitrary JavaScript on the MongoDB server.

Files changed

  • lib/mongoid/config.rb — new allow_unsafe_query_operators option (default: true)
  • lib/mongoid/criteria/queryable/selectable.rbALLOWED_QUERY_OPERATORS constant and guard in expr_query
  • spec/mongoid/criteria/queryable/selectable_where_spec.rb — 14 new examples covering the guard
  • Gemfile — add ostruct for Ruby 4.0+ compatibility

Test plan

  • 14 new examples in selectable_where_spec.rb covering blocked operators, allowlisted operators, and opt-in strict mode
  • All 1681 queryable specs pass with no regressions
  • RuboCop reports no offenses

Jira: https://jira.mongodb.org/browse/MONGOID-5939

Add an allowlist of permitted top-level query operators in expr_query.
By default, operators not in the list ($where, $function, etc.) raise
Errors::InvalidQuery. Set Mongoid.allow_unsafe_query_operators = true
to restore the previous pass-through behavior.

Also add gem 'ostruct' for Ruby 4.0+ compatibility.
@comandeo-mongo comandeo-mongo force-pushed the MONGOID-5939-operator-injection-guard branch from 1ec9d21 to c4cf5c8 Compare June 26, 2026 13:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant