Repository navigation
Double RLS application in virtual datasets for guest users (regression from PR #36061) #37359
Copy link
Copy link
Closed
Labels
#bug:regressionBugs that are identified as regessionsBugs that are identified as regessionsauthentication:row-level-securityRelated to Row Level SecurityRelated to Row Level Security
Description
Bug description
Summary:
PR #36061 "fix: RLS in virtual datasets" introduced a regression causing double RLS application for guest users with embedded dashboards. This is similar to #34894 (double time filter application) fixed in PR #35890.
Steps to Reproduce:
- Create a physical dataset for table
my_table - Create a virtual dataset with SQL referencing that table:
SELECT * FROM my_schema.my_table WHERE some_column = 'value'
- Create a dashboard with a chart using this virtual dataset
- Generate a guest token with RLS clause:
tenant_id = 123 - Open the embedded dashboard with this guest token
- Observe SQL error with incorrect table alias
Expected behavior:
RLS should be applied once - either to the underlying table OR to the virtual dataset output.
Actual behavior:
RLS is applied twice:
- First by
apply_rls()inmodels/helpers.py:2047-2057(wraps underlying table in subquery) - Second by
get_sqla_row_level_filters()inmodels/helpers.py:3198(adds WHERE clause to virtual dataset query)
Generated SQL example:
SELECT ... FROM (
SELECT * FROM my_schema.my_table
WHERE tenant_id = 123 -- First RLS applied to underlying table (correct)
) AS `my_schema.my_table`
WHERE my_table.tenant_id = 123 -- Second RLS applied with WRONG alias!
GROUP BY ...The second WHERE clause uses my_table.tenant_id but the subquery is aliased as my_schema.my_table, causing SQL errors like:
Unknown expression or function identifier 'my_table.tenant_id'
Root Cause:
get_from_clause()inmodels/helpers.py:2047-2057callsapply_rls()which wraps tables referenced in virtual dataset SQL with subqueries containing RLS predicatesget_sqla_query()inmodels/helpers.py:3198callsget_sqla_row_level_filters()which adds guest token RLS to the outer WHERE clause- For guest users with embedded dashboards, both mechanisms fire independently, causing double application with mismatched aliases
Related:
- PR fix(datasets): prevent double time filter application in virtual datasets #35890 fixed an identical pattern for time filters (double time filter application)
- PR fix: RLS in virtual datasets #36061 introduced this regression (merged 2025-11-14)
Screenshots/recordings
N/A - backend SQL generation issue
Superset version
6.0.0
Python version
3.11
Node version
18 or greater
Browser
Not applicable
Additional context
- Feature flags enabled:
EMBEDDED_SUPERSET - This is a regression - worked correctly in Superset 5.x
- No configuration workaround available
- Workaround: use physical datasets instead of virtual datasets (not always possible)
Checklist
- I have searched Superset docs and Slack and didn't find a solution to my problem.
- I have searched the GitHub issue tracker and didn't find a similar bug report.
- I have checked Superset's logs for errors and if I found a relevant Python stacktrace, I included it here as text in the "additional context" section.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
#bug:regressionBugs that are identified as regessionsBugs that are identified as regessionsauthentication:row-level-securityRelated to Row Level SecurityRelated to Row Level Security
Activity
[-]fix: Double RLS application in virtual datasets for guest users (regression from PR #36061)[/-][+]Double RLS application in virtual datasets for guest users (regression from PR #36061)[/+]dosubot commentedon Jan 22, 2026
This regression happens because RLS is applied twice for guest users with embedded dashboards using virtual datasets: once by wrapping the underlying table in a subquery with RLS predicates (
apply_rls()), and again by adding RLS filters to the outer query (get_sqla_row_level_filters()). This double application leads to SQL alias mismatches and errors, since the outer WHERE clause references an alias that doesn't exist after the subquery rewrite. The pattern is nearly identical to the previously fixed double time filter bug (PR #35890). There’s currently no config workaround except using physical datasets, which isn’t always practical. No open PR or issue addresses this regression yet, so a fix will likely require logic to prevent RLS from being applied twice in this scenario—potentially by detecting when RLS has already been pushed down into the subquery and skipping the outer filter application.You can review the relevant code and logic in models/helpers.py and superset/utils/rls.py.
To reply, just mention @dosu.
How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other
fix(embedded): prevent double RLS application in virtual datasets
LPD-18496 prevent guest RLS injection into virtual dataset inner tables