Skip to content

fix(mcp): harden the embedded-guest chart data-read path - #43066

Open
gabotorresruiz wants to merge 1 commit into
apache:masterfrom
gabotorresruiz:fix/mcp-guest-data-read-fastfollow
Open

fix(mcp): harden the embedded-guest chart data-read path#43066
gabotorresruiz wants to merge 1 commit into
apache:masterfrom
gabotorresruiz:fix/mcp-guest-data-read-fastfollow

Conversation

@gabotorresruiz

Copy link
Copy Markdown
Contributor

SUMMARY

Follow-up to the embedded-guest MCP data-read work (#41753). The max-effort review of that PR fixed the high-severity findings in-line and deferred a batch of lower-severity correctness, robustness, and coverage gaps; this PR clears that batch.

Two things up front, because these are intentionally small:

  • None is a security bypass. Guest chart data stays gated by raise_for_access on every path. These are about not returning a raw 500/opaque error and about internal consistency, not about what a guest can access.
  • None changes behavior for non-guest principals. Every change is either guest-only or a no-op for existing callers.

Grouped by area:

Guest dashboard scoping (utils/filters.py, dashboards/filters.py)

  • A dashboard slug is a valid guest-token resource id (Dashboard.get accepts it), but it was routed to Dashboard.id.in_([slug]), which raises a cast error/500 on strict backends. It now routes to Dashboard.slug.
  • The dashboard-list guest filter had its own copy of the scoping logic that used an either/or (uuid or int), so a token mixing uuid and int ids silently dropped the int-id dashboards — disagreeing with the chart-list filter. Both now use the shared guest_embedded_dashboard_filter, so visibility is consistent and the duplicate branch is gone.

get_chart_data / get_chart_preview robustness

  • row_limit can arrive as a string (cached form_data). The no-context path already coerced it; the using_unsaved_state and _query_from_form_data paths did not, and a string could 500 in apply_max_row_limit. Now coerced on all paths.
  • The form_data_key-only path had no guest handling: the unsaved-chart cache is not scoped to a guest's dashboards, so a guest failed opaquely downstream. Guests are now denied cleanly there.
  • The dataset pre-check was skipped entirely for guests, so a deleted dataset surfaced a raw error instead of the clean DatasetNotAccessible contract. It now runs for guests with check_access=False — existence check kept (clean error), RBAC access check skipped (guests are authorized via the dashboard context, not dataset RBAC).

MCP config / cleanup (mcp_config.py, auth.py)

  • get_mcp_config did not forward MCP_RESTRICTED_TOOL_POLICY, so a policy set at the mcp_config layer was dropped in standalone MCP mode. Now forwarded.
  • The 7-tool guest allow-list was duplicated as two literals kept in sync by a comment (and a test). auth.py now derives it from the single mcp_config source; the now-redundant sync test is removed.

Tests

  • Added tool-level guest tests for get_chart_data (the highest-value guest tool): the data query is pinned to the token's dashboard, the dataset check runs existence-only for guests, an out-of-scope chart is denied, and the form_data_key-only path is denied.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A (backend/MCP correctness).

TESTING INSTRUCTIONS

  • pytest tests/unit_tests/mcp_service/chart/tool/test_get_chart_data.py tests/unit_tests/mcp_service/chart/tool/test_get_chart_preview.py tests/unit_tests/mcp_service/test_guest_token_auth.py tests/unit_tests/mcp_service/test_guest_scope.py
  • pytest tests/unit_tests/utils/filters_test.py tests/unit_tests/dashboards/
  • All green locally; ruff and ruff format clean.

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
  • Introduces new feature or API
  • Removes existing feature or API

@netlify

netlify Bot commented Aug 11, 2026

Copy link
Copy Markdown

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit 63b3c18
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6a7de7442dbf260008a1e673
😎 Deploy Preview https://deploy-preview-43066--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@gabotorresruiz
gabotorresruiz force-pushed the fix/mcp-guest-data-read-fastfollow branch from 393151d to c695220 Compare August 11, 2026 17:04
@gabotorresruiz
gabotorresruiz force-pushed the fix/mcp-guest-data-read-fastfollow branch from c695220 to cc2c4af Compare August 11, 2026 17:25
@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 28.57143% with 20 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.24%. Comparing base (e2bb33b) to head (63b3c18).

Files with missing lines Patch % Lines
superset/mcp_service/chart/tool/get_chart_data.py 0.00% 15 Missing ⚠️
superset/dashboards/filters.py 66.66% 2 Missing ⚠️
superset/mcp_service/chart/chart_utils.py 0.00% 1 Missing ⚠️
...perset/mcp_service/chart/tool/get_chart_preview.py 50.00% 1 Missing ⚠️
superset/utils/filters.py 0.00% 1 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (e2bb33b) and HEAD (63b3c18). Click for more details.

HEAD has 15 uploads less than BASE
Flag BASE (e2bb33b) HEAD (63b3c18)
python 14 2
presto 2 1
hive 3 1
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #43066      +/-   ##
==========================================
- Coverage   66.67%   57.24%   -9.43%     
==========================================
  Files        2866     2866              
  Lines      162798   162777      -21     
  Branches    37507    37504       -3     
==========================================
- Hits       108546    93185   -15361     
- Misses      52130    68708   +16578     
+ Partials     2122      884    -1238     
Flag Coverage Δ
hive 38.20% <28.57%> (+<0.01%) ⬆️
mysql ?
postgres ?
presto 40.15% <28.57%> (+<0.01%) ⬆️
python 40.20% <28.57%> (-19.18%) ⬇️
sqlite ?
unit ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@rusackas
rusackas requested a review from rebenitez1802 August 11, 2026 19:59
@gabotorresruiz
gabotorresruiz marked this pull request as ready for review August 11, 2026 20:37
@dosubot dosubot Bot added authentication:access-control Rlated to access control embedded labels Aug 11, 2026

@rebenitez1802 rebenitez1802 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated multi-reviewer pass (correctness + adversarial security + test coverage). Posting the one blocker and the medium items. The security model itself held up — no boundary break, and the guest filter refactor actually narrows scope. Lower-severity nits omitted here.

The blocker was verified end-to-end against validate_chart_datasetDatasetDAO.find_by_idDatasourceFilter (no guest carve-out), cross-checked against the sibling get_chart_info, which still skips the pre-check for guests.

Comment thread superset/mcp_service/chart/tool/get_chart_data.py
Comment thread superset/mcp_service/chart/tool/get_chart_preview.py Outdated
Comment thread tests/unit_tests/mcp_service/chart/tool/test_get_chart_data.py
Comment thread tests/unit_tests/mcp_service/chart/tool/test_get_chart_data.py
Comment thread superset/utils/filters.py Outdated
@gabotorresruiz
gabotorresruiz force-pushed the fix/mcp-guest-data-read-fastfollow branch from cc2c4af to a0f9872 Compare August 11, 2026 20:51
@github-actions github-actions Bot removed the embedded label Aug 11, 2026
@gabotorresruiz

gabotorresruiz commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

@rebenitez1802 Thanks for the thorough pass, genuinely useful. Fixed the blocker at the root in validate_chart_dataset (skip_base_filter=not check_access) and added tests that actually fail without the fix, for the guest existence path, the row_limit coercion, and the slug branch. Replies inline, all threads addressed.

Comment thread tests/unit_tests/mcp_service/chart/tool/test_get_chart_data.py Outdated
Comment thread superset/dashboards/filters.py Outdated
Comment thread superset/mcp_service/chart/tool/get_chart_data.py
@gabotorresruiz
gabotorresruiz force-pushed the fix/mcp-guest-data-read-fastfollow branch 2 times, most recently from 69ad36a to cad8a7b Compare August 11, 2026 21:07

@bito-code-review bito-code-review Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Agent Run #a1a7e2

Actionable Suggestions - 1
  • superset/dashboards/filters.py - 1
Additional Suggestions - 1
  • tests/unit_tests/subjects/test_filters.py - 1
    • Redundant inline import · Line 77-77
      This import is redundant — `DashboardAccessFilter` is already imported at the module level (lines 50, 63). Per rule [12745], inline imports should only be used when a circular dependency exists.
Review Details
  • Files reviewed - 13 · Commit Range: cad8a7b..cad8a7b
    • superset/daos/dashboard.py
    • superset/dashboards/filters.py
    • superset/mcp_service/auth.py
    • superset/mcp_service/chart/chart_utils.py
    • superset/mcp_service/chart/tool/get_chart_data.py
    • superset/mcp_service/chart/tool/get_chart_preview.py
    • superset/mcp_service/mcp_config.py
    • superset/utils/filters.py
    • tests/unit_tests/mcp_service/chart/test_chart_utils.py
    • tests/unit_tests/mcp_service/chart/tool/test_get_chart_data.py
    • tests/unit_tests/mcp_service/test_guest_token_auth.py
    • tests/unit_tests/subjects/test_filters.py
    • tests/unit_tests/utils/filters_test.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Comment thread superset/dashboards/filters.py Outdated

@rebenitez1802 rebenitez1802 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once CI is green

@gabotorresruiz
gabotorresruiz force-pushed the fix/mcp-guest-data-read-fastfollow branch from cad8a7b to 009022e Compare August 12, 2026 16:38
Comment thread superset/utils/filters.py Outdated
Comment thread superset/mcp_service/chart/tool/get_chart_preview.py Outdated
Comment thread superset/mcp_service/chart/tool/get_chart_data.py
Comment thread superset/utils/filters.py Outdated
@gabotorresruiz
gabotorresruiz force-pushed the fix/mcp-guest-data-read-fastfollow branch from 009022e to e85ed21 Compare August 12, 2026 17:14
@bito-code-review

bito-code-review Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #fbd25f

Actionable Suggestions - 0
Additional Suggestions - 2
  • superset/mcp_service/chart/tool/get_chart_preview.py - 1
    • Inline import breaks convention · Line 1299-1299
      Inline import at line 1299 breaks module-level convention used by all other MCP files in this package. `get_chart_data.py` imports `guest_scope` at module level (line 38), establishing the pattern. If a circular dependency exists, document it with a comment; otherwise hoist to top-level.
  • tests/unit_tests/utils/filters_test.py - 1
    • Duplicate module import · Line 181-181
      Redundant inline import; `False_` is already imported at line 92. Per project style, inline imports are only justified for circular dependencies.
Filtered by Review Rules

Bito filtered these suggestions based on rules created automatically for your feedback. Manage rules.

  • tests/unit_tests/mcp_service/test_guest_token_auth.py - 1
Review Details
  • Files reviewed - 13 · Commit Range: e85ed21..e85ed21
    • superset/daos/dashboard.py
    • superset/dashboards/filters.py
    • superset/mcp_service/auth.py
    • superset/mcp_service/chart/chart_utils.py
    • superset/mcp_service/chart/tool/get_chart_data.py
    • superset/mcp_service/chart/tool/get_chart_preview.py
    • superset/mcp_service/mcp_config.py
    • superset/utils/filters.py
    • tests/unit_tests/mcp_service/chart/test_chart_utils.py
    • tests/unit_tests/mcp_service/chart/tool/test_get_chart_data.py
    • tests/unit_tests/mcp_service/test_guest_token_auth.py
    • tests/unit_tests/subjects/test_filters.py
    • tests/unit_tests/utils/filters_test.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@gabotorresruiz
gabotorresruiz force-pushed the fix/mcp-guest-data-read-fastfollow branch from e85ed21 to 9e40ff5 Compare August 12, 2026 20:50
@github-actions github-actions Bot added the doc Namespace | Anything related to documentation label Aug 12, 2026
@gabotorresruiz
gabotorresruiz force-pushed the fix/mcp-guest-data-read-fastfollow branch from 9e40ff5 to efaca68 Compare August 13, 2026 14:43
@github-actions github-actions Bot removed the doc Namespace | Anything related to documentation label Aug 13, 2026
Follow-up to the embedded-guest MCP data-read work (apache#41753): a batch of
lower-severity correctness, robustness, and coverage gaps deferred from that
review. None change behavior for non-guest principals, and none is a data
bypass — guest chart data stays gated by raise_for_access on every path.

- Route a dashboard slug resource id to Dashboard.slug instead of binding it
  to the integer id column (avoids a cast error/500 on strict backends), in the
  shared guest_embedded_dashboard_filter.
- Make the dashboard-list guest filter reuse guest_embedded_dashboard_filter so
  it matches the chart-list filter (both OR uuid/int/slug ids); a mixed-id token
  no longer hides int-id dashboards. Removes the duplicated branch.
- Coerce row_limit to int on the using_unsaved_state and _query_from_form_data
  paths of get_chart_data (a string row_limit could 500 in apply_max_row_limit).
- Deny a guest cleanly on the form_data_key-only path (the unsaved-chart cache
  is not scoped to the token's dashboards) instead of failing opaquely.
- Run the dataset existence pre-check for guests with check_access=False so a
  deleted dataset returns the clean DatasetNotAccessible contract rather than a
  raw error (get_chart_data and get_chart_preview).
- Forward MCP_RESTRICTED_TOOL_POLICY through get_mcp_config so a policy set at
  the mcp_config layer is not dropped in standalone MCP mode.
- Derive the auth.py guest allow-list from the single mcp_config source instead
  of a duplicated literal; drop the now-redundant sync test.
- Add tool-level guest tests for get_chart_data (dashboard-pinned query,
  existence-only dataset check, out-of-scope denial, form_data_key denial).
@gabotorresruiz
gabotorresruiz force-pushed the fix/mcp-guest-data-read-fastfollow branch from efaca68 to 63b3c18 Compare August 13, 2026 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants