Skip to content

Fix NoSQL object comparison being too strict#648

Merged
bitterpanda63 merged 1 commit into
mainfrom
fix/nosql-object-comparison-too-strict
Jun 1, 2026
Merged

Fix NoSQL object comparison being too strict#648
bitterpanda63 merged 1 commit into
mainfrom
fix/nosql-object-comparison-too-strict

Conversation

@bitterpanda63
Copy link
Copy Markdown
Member

@bitterpanda63 bitterpanda63 commented Jun 1, 2026

Ports AikidoSec/firewall-node#1032 to Python.

Problem: The NoSQL injection detector used exact equality (filtered_input == filter_part) when comparing user-supplied $ operators to the MongoDB filter. This caused false negatives when:

  • The app merges user operators with its own (e.g. adds $exists: true alongside user's $ne: null)
  • The app prepends its own $ keys before the user's operators

Fix: Replace exact equality with is_user_operators_subset_of() — checks that every user-supplied operator exists in the filter with the same value, instead of requiring the objects to be identical. An empty operator dict never matches.

All 9 new test cases from the Node.js PR are ported.

Summary by Aikido

Security Issues: 0 🔍 Quality Issues: 1 Resolved Issues: 0

⚡ Enhancements

  • Added is_user_operators_subset_of helper to compare operator subsets accurately

🐛 Bugfixes

  • Relaxed NoSQL operator comparison to allow subset matches

More info

Comment on lines +60 to +71
def is_user_operators_subset_of(user_operators, filter_operators):
"""
Returns True if every operator in user_operators is present in filter_operators
with the same value — i.e. the user-supplied operators are a subset of the filter.
An empty user_operators dict never matches (no operators = no injection).
"""
has_keys = False
for key, value in user_operators.items():
if key not in filter_operators or filter_operators[key] != value:
return False
has_keys = True
return has_keys
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_user_operators_subset_of uses a has_keys flag to detect empty input. Add an early guard (if not user_operators: return False) to simplify the function and remove the auxiliary variable.

Show fix
Suggested change
def is_user_operators_subset_of(user_operators, filter_operators):
"""
Returns True if every operator in user_operators is present in filter_operators
with the same valuei.e. the user-supplied operators are a subset of the filter.
An empty user_operators dict never matches (no operators = no injection).
"""
has_keys = False
for key, value in user_operators.items():
if key not in filter_operators or filter_operators[key] != value:
return False
has_keys = True
return has_keys
def is_user_operators_subset_of(user_operators, filter_operators):
if not user_operators:
return False
for key, value in user_operators.items():
if key not in filter_operators or filter_operators[key] != value:
return False
return True
Details

✨ AI Reasoning
​The new function is_user_operators_subset_of checks whether the user_operators dict is non-empty and that each entry matches in filter_operators. Currently it iterates all items and uses a has_keys flag to detect emptiness, returning that at the end. An explicit early-return guard (if not user_operators: return False) would make the intent clearer and remove the auxiliary has_keys state, improving readability and maintainability.

Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

@bitterpanda63 bitterpanda63 merged commit 4af94ea into main Jun 1, 2026
273 of 281 checks passed
@bitterpanda63 bitterpanda63 deleted the fix/nosql-object-comparison-too-strict branch June 1, 2026 15:43
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.

2 participants