Skip to content

fix(AF-1092): drop RLS-bound predicate text from cost estimates - #1095

Merged
babltiga merged 3 commits into
mainfrom
fix/AF-1092-estimate-plan-rls-redaction
Sep 24, 2026
Merged

babltiga merged 3 commits into
mainfrom
fix/AF-1092-estimate-plan-rls-redaction

Conversation

@babltiga

Copy link
Copy Markdown
Contributor

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), MySQL attached_condition, MongoDB stage filter. That text was stored in query_estimates.plan (each node's detail) and raw_plan, and GET /queries/{id} returned it to every QUERY_VIEW_ALL holder, 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's detail set to null and raw_plan null. 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 strips detail and raw_plan from every stored estimate (a recursive pg_temp plpgsql function, dropped afterwards). Historical predicate text is lost; the figures stay.
  • Docs: 03-data-model (query_estimates), 04-api-spec (cost_estimate), 05-backend (cost estimate section), 07-security (row-level security).

No frontend change: CostEstimatePanel / PlanTree already render a null detail and a missing raw_plan. The ad-hoc POST /queries/dry-run is 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.
  • ApplicationModulesTest and ApiPackageDependencyTest pass. The full mvn verify was not run locally; CI covers it.

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
@github-actions

github-actions Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Backend Test Results

10 275 tests  +4   10 275 ✅ +4   11m 38s ⏱️ +8s
 1 142 suites +1        0 💤 ±0 
 1 142 files   +1        0 ❌ ±0 

Results for commit fe5c933. ± Comparison against base commit a8e3809.

♻️ This comment has been updated with latest results.

@github-actions

Copy link
Copy Markdown
Contributor

Backend Code Coverage

Overall Project 94.75% 🍏
Files changed 100% 🍏

File Coverage
DefaultQueryCostEstimateService.java 95.94% 🍏

@babltiga
babltiga merged commit fd005b4 into main Sep 24, 2026
54 of 56 checks passed
@babltiga
babltiga deleted the fix/AF-1092-estimate-plan-rls-redaction branch September 24, 2026 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

proxy: cost estimate plan leaks row-security bound values

1 participant