Uh oh!
There was an error while loading. Please reload this page.
[fix](fe) Fix Ranger column-level privilege bypass when CTE combined - #61741
Conversation
Thearas
commented
Mar 26, 2026
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
morrySnow
commented
Mar 26, 2026
add test please |
smith1000
commented
Mar 26, 2026
sure |
214c8ba to
cd94a32Comparesmith1000
commented
Mar 26, 2026
@morrySnow Test cases added. Please take a look |
Hi, @smith1000, It is expected that the entire query statement checks permissions only once, which helps prevent redundant permission checks. In addition, placing the permission flag in the StatementContext is intentional. Consider this scenario: a user has access to view_a, but does not have access to table_b inside view_a. In this case, two CascadeContexts are generated—one for the scope outside view_a, and one for the scope inside view_a. The expected behavior is that if the user has access to view_a, they can bypass the permission check on table_b and query it through the view. This requirement implies that the permission information needs to be shared in a common place (i.e., StatementContext). Therefore, for this issue, the expected behavior is to traverse the outermost query. If a CTE reference is encountered, the traversal should continue into the CTE to perform a complete permission check. Once the entire traversal is finished, the StatementContext should be marked as having completed the permission check. |
924060929
commented
Mar 26, 2026
/review |
Code Review SummaryVerdict: No issues found. The change is correct, minimal, and well-tested. Change OverviewThis PR fixes a security bug (Ranger column-level privilege bypass with CTE+JOIN) by moving the Critical Checkpoint Conclusions
|
smith1000
commented
Mar 26, 2026
hi, @924060929 , |
cd94a32 to
c92af90Comparesmith1000
commented
Mar 30, 2026
hi, @924060929 I've reworked the fix based on your feedback. The
All 12 scenarios passed. The fix correctly denies CTE+JOIN bypass while preserving view permission passthrough. |
924060929
commented
Mar 30, 2026
/review |
Code Review SummaryPR: fix Fix Ranger column-level privilege bypass when CTE combined with JOIN Overall AssessmentThis is a well-targeted security fix for a privilege bypass vulnerability (Issue #61631). The approach is sound: when a CTE is materialized (not inlined due to Critical Checkpoint Conclusions1. Goal and correctness: 2. Modification minimality: 3. Concurrency: 4. Lifecycle management: 5. Execution ordering: 6. Pre-rewrite producer plan correctness: 7. 8. Edge cases verified:
9. Functionally parallel code paths: 10. Configuration items: 11. Incompatible changes: 12. Test coverage: 13. Observability: 14. Performance: Minor Observations (Non-blocking)
VerdictNo issues found. The fix is correct, minimal, well-tested, and handles edge cases properly. The security vulnerability is properly addressed. |
| @@ -264,6 +264,8 @@ public enum TableFrom { | |||
| private boolean privChecked; | |||
| private final Map<CTEId, Plan> cteProducerPlansForPrivCheck = Maps.newHashMap(); | |||
There was a problem hiding this comment.
I think you should reuse StatementContext.cteIdToProducer and StatementContext.getCteProducerByCteId()
morrySnow
commented
Apr 16, 2026
@smith1000 are you still dealing with this issue? |
seawinde
commented
Apr 16, 2026
run buildall |
hello-stephen
commented
Apr 16, 2026
FE UT Coverage ReportIncrement line coverage |
hello-stephen
commented
Apr 16, 2026
FE Regression Coverage ReportIncrement line coverage |
smith1000
commented
Apr 21, 2026
Hi @morrySnow, yes I'm still working on this. Sorry for the delayed response — I had some personal changes going on recently and was away for a while. I'm back now and will submit a new revision soon based on @924060929's review feedback. Thanks for keeping this PR alive. |
…with JOIN ### What problem does this PR solve? Issue Number: closeapache#61631 Problem Summary: When a CTE (WITH ... AS) is referenced multiple times in a JOIN query and is not inlined (due to inlineCTEReferencedThreshold), the CheckPrivileges rule does not traverse the CTE producer subtree because LogicalCTEConsumer is a leaf node in the plan tree. This means column-level privileges on the CTE's underlying tables are never checked, allowing users without proper column access to bypass Ranger authorization. The fix adds a visitLogicalCTEConsumer override in CheckPrivileges that explicitly retrieves the CTE producer plan (stored by RewriteCteChildren) and traverses it for privilege checking. The privChecked flag remains on StatementContext to preserve the view permission passthrough mechanism. ### Release note Fixed a security issue where Ranger column-level privileges could be bypassed when using CTE (WITH ... AS) combined with JOIN queries. Users without proper column access permissions could read restricted columns through CTE+JOIN patterns. ### Check List (For Author) - Test: Unit Test - Behavior changed: No - Does this need documentation: No
### What problem does this PR solve? Related PR: closeapache#61631 Problem Summary: Add unit tests to verify that column-level privileges are properly enforced when CTE is used with JOIN queries. Tests cover: - CTE + LEFT JOIN on fully-privileged table (should succeed) - CTE + LEFT JOIN accessing restricted column (should be denied) - CTE + LEFT JOIN accessing only allowed columns (should succeed) - CTE + INNER JOIN accessing restricted column (should be denied) ### Release note None ### Check List (For Author) - Test: Unit Test - Behavior changed: No - Does this need documentation: No
c92af90 to
6b3db5aComparesmith1000
commented
Apr 22, 2026
Hi @924060929, Thanks for the detailed review feedback. I've reworked the fix accordingly: Changes in this revision:
Local verification: We are currently running Doris 4.0.2 in production. Since Note on The
|
morrySnow
commented
May 6, 2026
run buildall |
PR approved by at least one committer and no changes requested. |
PR approved by anyone and no changes requested. |
Uh oh!
There was an error while loading. Please reload this page.
…61741) ### What problem does this PR solve? Issue Number: close#61631 Problem Summary: When a CTE (WITH ... AS) is referenced multiple times in a JOIN query and is not inlined (due to inlineCTEReferencedThreshold), the CheckPrivileges rule does not traverse the CTE producer subtree because LogicalCTEConsumer is a leaf node in the plan tree. This means column-level privileges on the CTE's underlying tables are never checked, allowing users without proper column access to bypass Ranger authorization. The fix adds a `visitLogicalCTEConsumer` override in `CheckPrivileges` that explicitly retrieves the CTE producer plan (stored by `RewriteCteChildren`) and traverses it for privilege checking. The `privChecked` flag remains on `StatementContext` to preserve the view permission passthrough mechanism. ### Release note Fixed a security issue where Ranger column-level privileges could be bypassed when using CTE (WITH ... AS) combined with JOIN queries. Users without proper column access permissions could read restricted columns through CTE+JOIN patterns. ### Check List (For Author) - Test: Unit Test / Manual test (verified with Ranger 2.7.0 + Doris 4.0.2 environment) - Behavior changed: No - Does this need documentation: No --------- Co-authored-by: geshengli <geshengli@wps.cn>
…61741) ### What problem does this PR solve? Issue Number: close#61631 Problem Summary: When a CTE (WITH ... AS) is referenced multiple times in a JOIN query and is not inlined (due to inlineCTEReferencedThreshold), the CheckPrivileges rule does not traverse the CTE producer subtree because LogicalCTEConsumer is a leaf node in the plan tree. This means column-level privileges on the CTE's underlying tables are never checked, allowing users without proper column access to bypass Ranger authorization. The fix adds a `visitLogicalCTEConsumer` override in `CheckPrivileges` that explicitly retrieves the CTE producer plan (stored by `RewriteCteChildren`) and traverses it for privilege checking. The `privChecked` flag remains on `StatementContext` to preserve the view permission passthrough mechanism. ### Release note Fixed a security issue where Ranger column-level privileges could be bypassed when using CTE (WITH ... AS) combined with JOIN queries. Users without proper column access permissions could read restricted columns through CTE+JOIN patterns. ### Check List (For Author) - Test: Unit Test / Manual test (verified with Ranger 2.7.0 + Doris 4.0.2 environment) - Behavior changed: No - Does this need documentation: No --------- Co-authored-by: geshengli <geshengli@wps.cn>
…pache#61741) ### What problem does this PR solve? Issue Number: closeapache#61631 Problem Summary: When a CTE (WITH ... AS) is referenced multiple times in a JOIN query and is not inlined (due to inlineCTEReferencedThreshold), the CheckPrivileges rule does not traverse the CTE producer subtree because LogicalCTEConsumer is a leaf node in the plan tree. This means column-level privileges on the CTE's underlying tables are never checked, allowing users without proper column access to bypass Ranger authorization. The fix adds a `visitLogicalCTEConsumer` override in `CheckPrivileges` that explicitly retrieves the CTE producer plan (stored by `RewriteCteChildren`) and traverses it for privilege checking. The `privChecked` flag remains on `StatementContext` to preserve the view permission passthrough mechanism. ### Release note Fixed a security issue where Ranger column-level privileges could be bypassed when using CTE (WITH ... AS) combined with JOIN queries. Users without proper column access permissions could read restricted columns through CTE+JOIN patterns. ### Check List (For Author) - Test: Unit Test / Manual test (verified with Ranger 2.7.0 + Doris 4.0.2 environment) - Behavior changed: No - Does this need documentation: No --------- Co-authored-by: geshengli <geshengli@wps.cn>
What problem does this PR solve?
Issue Number: close#61631
Problem Summary: When a CTE (WITH ... AS) is referenced multiple times in a
JOIN query and is not inlined (due to inlineCTEReferencedThreshold), the
CheckPrivileges rule does not traverse the CTE producer subtree because
LogicalCTEConsumer is a leaf node in the plan tree. This means column-level
privileges on the CTE's underlying tables are never checked, allowing users
without proper column access to bypass Ranger authorization.
The fix adds a
visitLogicalCTEConsumeroverride inCheckPrivilegesthatexplicitly retrieves the CTE producer plan (stored by
RewriteCteChildren)and traverses it for privilege checking. The
privCheckedflag remains onStatementContextto preserve the view permission passthrough mechanism.Release note
Fixed a security issue where Ranger column-level privileges could be bypassed
when using CTE (WITH ... AS) combined with JOIN queries. Users without proper
column access permissions could read restricted columns through CTE+JOIN
patterns.
Check List (For Author)