fix(mcp): escape LIKE wildcards in MCP list tool search filters#40682
Conversation
search='%' passed all validators and produced ILIKE '%%', matching every row. Add _escape_like() helper that escapes \, %, and _ before they are interpolated into ILIKE patterns, and apply it at both call sites in BaseDAO._build_query() and BaseDAO.list(). Adds a regression test that asserts search='%' does not match rows whose names contain no percent sign.
Code Review Agent Run #60dba8Actionable Suggestions - 0Additional Suggestions - 2
Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #40682 +/- ##
==========================================
- Coverage 63.96% 63.96% -0.01%
==========================================
Files 2658 2658
Lines 143095 143123 +28
Branches 32907 32910 +3
==========================================
+ Hits 91537 91544 +7
- Misses 49991 50012 +21
Partials 1567 1567
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Posting on Richard's behalf — this is his PR reviewer agent. Forward any pushback to him and he'll loop me back in. Left one functional note below. The direct Functional — worth fixing before merge
Praise
|
The wildcard operator lambdas (sw, ew, ct, like, ilike) in operator_map
also interpolated user values directly into LIKE/ILIKE patterns. A caller
could send column_operators=[{col, opr:ilike, value:%}] and receive every
row regardless of base_filter.
Move _escape_like to module level (before operator_map) and apply it in
all five wildcard lambdas. Remove the @staticmethod duplicate from BaseDAO.
Adds a regression test covering all five operators with value='%'.
Code Review Agent Run #43f61aActionable Suggestions - 0Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
SUMMARY
All 10+ MCP list tools (
list_users,list_rls_filters,list_roles,list_reports, etc.) delegate toBaseDAO._build_query()andBaseDAO.list()insuperset/daos/base.py. Both methods build search filters with:search="%"is a single character that passes every existing Pydantic validator. The resulting patternILIKE '%%'matches every row, allowing an admin to enumerate all records regardless of the intended search intent — LIKE wildcard injection.Fix: Added a
_escape_like()static method that escapes\,%, and_before interpolation, and passesescape="\\"toilike(). Applied at both call sites.All affected tools are admin-only (the MCP API enforces admin authentication), so blast radius is limited. Related prior fix for
find_users: #40631.BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
N/A — backend-only change.
TESTING INSTRUCTIONS
search="%"returns 0 results for an admin with no users whose username contains a literal%.search="admin"still returns users matching "admin" normally.ADDITIONAL INFORMATION