Fix NoSQL object comparison being too strict#648
Conversation
| 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 |
There was a problem hiding this comment.
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
| 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 | |
| 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
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:$exists: truealongside user's$ne: null)$keys before the user's operatorsFix: 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
⚡ Enhancements
🐛 Bugfixes
More info