fix(AF-1092): drop RLS-bound predicate text from cost estimates - #1095
Merged
Merged
Conversation
The estimate dry-run binds the submitter's row-security values and engines inline them into plan predicate text, which was persisted and shown to every QUERY_VIEW_ALL holder. When row security applies, store the plan tree without node detail and without the raw plan. V188 strips the rows stored before the fix. Closes #1092
Contributor
…plan-rls-redaction # Conflicts: # docs/07-security.md
Contributor
Backend Code Coverage
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1092
What
The persisted pre-flight cost estimate (AF-624) could leak row-security bound values. The estimate dry-run binds the submitter's resolved row-security values, and engines inline them into plan predicate text — e.g. PostgreSQL
((email)::text = 'dana@…'::text), MySQLattached_condition, MongoDB stagefilter. That text was stored inquery_estimates.plan(each node'sdetail) andraw_plan, andGET /queries/{id}returned it to everyQUERY_VIEW_ALLholder, not just the submitter.DefaultQueryCostEstimateService: when a row-security directive was resolved for the submitter, or the engine reports an applied policy, the plan tree is stored with every node'sdetailset to null andraw_plannull. Operation, target, rows and cost are kept, so routing conditions, the AI prompt summary and approval-prediction features are unaffected.V188__redact_query_estimate_plan_predicates.sql: nothing recorded which existing estimates had row security applied, so this stripsdetailandraw_planfrom every stored estimate (a recursivepg_tempplpgsql function, dropped afterwards). Historical predicate text is lost; the figures stay.03-data-model(query_estimates),04-api-spec(cost_estimate),05-backend(cost estimate section),07-security(row-level security).No frontend change:
CostEstimatePanel/PlanTreealready render a nulldetailand a missingraw_plan. The ad-hocPOST /queries/dry-runis unchanged — it returns the plan only to the caller, about their own values, and stores nothing.Reviewer notes
Tests
DefaultQueryCostEstimateServiceTest: 3 new cases — text kept without row security, dropped when a policy resolves, dropped when only the engine reports an applied policy.QueryEstimatePlanRedactionMigrationIntegrationTest: migrates to V187, seeds leaking rows, applies V188 and asserts the values are gone while the figures and tree shape remain.ApplicationModulesTestandApiPackageDependencyTestpass. The fullmvn verifywas not run locally; CI covers it.