This is an automated email from the ASF dual-hosted git repository.

aminghadersohi pushed a commit to branch mcp-rls-plugins-99978
in repository https://gitbox.apache.org/repos/asf/superset.git

commit c470b7a8d49596f3948ec93d7c27de1274ec38d0
Author: Amin Ghadersohi <[email protected]>
AuthorDate: Thu May 21 04:25:19 2026 +0000

    fix(mcp): restore 'roles' to USER_DIRECTORY_FIELDS and bypass filter in RLS 
list tool
    
    'roles' on a dashboard/chart exposes who has access to the resource and
    should be stripped by the USER_DIRECTORY_FIELDS privacy filter.
    
    'roles' in an RLS filter is which roles the filter applies to — it is
    core filter data, not user-directory metadata. The RLS list tool now
    derives its column selection directly from ALL_RLS_COLUMNS (bypassing
    ModelListCore's USER_DIRECTORY_FIELDS filtering) so that RLS roles are
    selectable while dashboard roles remain hidden.
    
    Fixes three failing unit tests:
    - test_list_dashboards_omits_requested_user_directory_fields
    - test_get_allowed_fields_always_denies_user_directory_fields
    - test_filter_sensitive_data_strips_user_directory_fields_even_if_allowed
    
    Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
---
 superset/mcp_service/privacy.py                   |  1 +
 superset/mcp_service/rls/tool/list_rls_filters.py | 15 ++++++++++++++-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/superset/mcp_service/privacy.py b/superset/mcp_service/privacy.py
index 46af518710f..105a9492666 100644
--- a/superset/mcp_service/privacy.py
+++ b/superset/mcp_service/privacy.py
@@ -40,6 +40,7 @@ USER_DIRECTORY_FIELDS = frozenset(
         "last_saved_by_name",
         "owner",
         "owners",
+        "roles",
     }
 )
 
diff --git a/superset/mcp_service/rls/tool/list_rls_filters.py 
b/superset/mcp_service/rls/tool/list_rls_filters.py
index b08b9bc32d3..e72d032a96e 100644
--- a/superset/mcp_service/rls/tool/list_rls_filters.py
+++ b/superset/mcp_service/rls/tool/list_rls_filters.py
@@ -108,7 +108,20 @@ async def list_rls_filters(
             % (len(result.rls_filters), result.total_count)
         )
 
-        columns_to_filter = result.columns_requested
+        # Build column selection using ALL_RLS_COLUMNS as the source of truth,
+        # bypassing the USER_DIRECTORY_FIELDS privacy filter applied by
+        # ModelListCore. 'roles' in an RLS filter is which roles the filter
+        # applies to — core filter data — not user-directory metadata (like
+        # dashboard.roles, which exposes who has access to the resource).
+        if request.select_columns:
+            columns_to_filter = [
+                c for c in request.select_columns if c in ALL_RLS_COLUMNS
+            ]
+            if not columns_to_filter:
+                columns_to_filter = list(DEFAULT_RLS_COLUMNS)
+        else:
+            columns_to_filter = list(DEFAULT_RLS_COLUMNS)
+
         with 
event_logger.log_context(action="mcp.list_rls_filters.serialization"):
             return result.model_dump(
                 mode="json",

Reply via email to