Skip to content

Conversation

@aminghadersohi
Copy link
Contributor

@aminghadersohi aminghadersohi commented Jan 6, 2026

SUMMARY

Add embeddable charts with guest token authentication, accessible via both:

  1. MCP Tool (get_embeddable_chart) - For AI agents to create charts programmatically
  2. UI Button ("Embed chart" in chart dropdown) - For users to embed charts from dashboards

Key Features:

  • Ephemeral Charts: Uses permalink system with TTL (no database persistence needed)
  • Guest Token Support: New CHART_PERMALINK resource type for secure embedding
  • UI Integration: "Embed chart" button in dashboard chart header dropdown
  • MCP Integration: Tool for AI agents to generate embeddable charts

Architecture:

UI Flow:
Dashboard → Chart dropdown → "Embed chart" → Modal
          → POST /api/v1/embedded_chart/
          → Returns iframe_url + guest_token + embed code

MCP Flow:
AI Agent → get_embeddable_chart tool
         → Creates permalink + guest token
         → Returns iframe_url + guest_token + iframe_html

Both flows use:
/embedded/chart/?permalink_key=xxx → StatefulChart component

Files Changed:

  • superset/security/guest_token.py - Add CHART_PERMALINK enum
  • superset/security/manager.py - Add validation and access control logic
  • superset/embedded_chart/ - Backend module (api, view, exceptions)
  • superset/mcp_service/embedded_chart/ - MCP tool with schemas
  • superset-frontend/src/embeddedChart/ - Frontend entry point
  • superset-frontend/src/dashboard/components/EmbeddedChartModal/ - UI modal
  • superset-frontend/src/dashboard/components/SliceHeaderControls/ - Menu item

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

New "Embed chart" menu option:
Screenshot 2026-01-08 at 7 11 27 PM

Screenshot 2026-01-08 at 7 11 41 PM Screenshot 2026-01-08 at 7 12 56 PM Screenshot 2026-01-08 at 7 13 05 PM Screenshot 2026-01-08 at 7 33 23 PM Screenshot 2026-01-08 at 7 33 46 PM

Embedded chart rendering:

Embed chart menu option Embedded chart in external app

TESTING INSTRUCTIONS

Testing via UI

  1. Open a dashboard with charts
  2. Click the chart dropdown menu (3 dots)
  3. Click "Embed chart"
  4. Configure allowed domains (optional) and TTL
  5. Click "Generate Embed Code"
  6. Copy the generated code and paste into an HTML file
  7. Open the HTML file in a browser to see the embedded chart

Testing via MCP (for AI Agents)

1. List available charts:

// Use list_charts MCP tool
{"page_size": 10}

2. Get chart details:

// Use get_chart_info MCP tool
{"identifier": 123}

3. Create embeddable chart:

// Use get_embeddable_chart MCP tool
{
    "datasource_id": 22,
    "viz_type": "echarts_timeseries_bar",
    "form_data": {
        "x_axis": "genre",
        "metrics": [{
            "aggregate": "SUM",
            "column": {"column_name": "global_sales"},
            "expressionType": "SIMPLE",
            "label": "Total Global Sales"
        }]
    },
    "ttl_minutes": 60,
    "height": 500
}

4. Create test HTML file with returned values:

<!DOCTYPE html>
<html>
<head><title>Test Embedded Chart</title></head>
<body>
    <iframe
        id="embedded-chart"
        src="http://localhost:9081/embedded/chart/?permalink_key=PERMALINK_KEY_HERE"
        width="100%" height="500px" frameborder="0"
        sandbox="allow-scripts allow-same-origin allow-popups"
    ></iframe>
    <script>
        const GUEST_TOKEN = 'GUEST_TOKEN_HERE';
        const SUPERSET_URL = 'http://localhost:9081';
        const iframe = document.getElementById('embedded-chart');
        iframe.addEventListener('load', function() {
            const channel = new MessageChannel();
            iframe.contentWindow.postMessage({
                type: '__embedded_comms__', handshake: 'port transfer'
            }, SUPERSET_URL, [channel.port2]);
            setTimeout(function() {
                channel.port1.postMessage({
                    switchboardAction: 'emit', method: 'guestToken',
                    args: { guestToken: GUEST_TOKEN }
                });
            }, 100);
        });
    </script>
</body>
</html>

5. Open HTML file in browser and verify chart renders

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags: None (leverages existing embedded infrastructure)
  • Changes UI
  • Includes DB Migration
  • Introduces new feature or API
  • Removes existing feature or API

Comparison with PR #33424:
This PR takes a simpler approach than #33424:

  • No database model/migration needed (uses ephemeral permalinks)
  • Shares same CHART_PERMALINK guest token infrastructure
  • Lighter frontend (StatefulChart instead of Redux-based hydration)
  • Works for both AI agents (MCP) and users (UI button)

🤖 Generated with Claude Code

@codeant-ai-for-open-source
Copy link
Contributor

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@netlify
Copy link

netlify bot commented Jan 6, 2026

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit ccb0742
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/695fd1145abe800007c6863c
😎 Deploy Preview https://deploy-preview-36933--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

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

@github-actions github-actions bot added the api Related to the REST API label Jan 6, 2026
@dosubot dosubot bot added the change:frontend Requires changing the frontend label Jan 6, 2026
@codeant-ai-for-open-source
Copy link
Contributor

CodeAnt AI finished reviewing your PR.

@codeant-ai-for-open-source
Copy link
Contributor

💡 Enhance Your PR Reviews

We noticed that 3 feature(s) are not configured for this repository. Enabling these features can help improve your code quality and workflow:

🚦 Quality Gates

Status: Quality Gates are not enabled at the organization level
Learn more about Quality Gates

🎫 Jira Ticket Compliance

Status: Jira credentials file not found. Please configure Jira integration in your settings
Learn more about Jira Integration

⚙️ Custom Rules

Status: No custom rules configured. Add rules via organization settings or .codeant/review.json in your repository
Learn more about Custom Rules


Want to enable these features? Contact your organization admin or check our documentation for setup instructions.

@codecov
Copy link

codecov bot commented Jan 6, 2026

Codecov Report

❌ Patch coverage is 42.93333% with 214 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.72%. Comparing base (84279ac) to head (8128449).
⚠️ Report is 20 commits behind head on master.

Files with missing lines Patch % Lines
...ervice/embedded_chart/tool/get_embeddable_chart.py 0.00% 53 Missing ⚠️
superset/embedded_chart/api.py 39.75% 50 Missing ⚠️
superset/embedded_chart/view.py 38.59% 35 Missing ⚠️
superset/charts/api.py 53.03% 31 Missing ⚠️
superset/mcp_service/embedded_chart/schemas.py 0.00% 20 Missing ⚠️
superset/security/manager.py 40.00% 11 Missing and 1 partial ⚠️
superset/commands/chart/delete.py 60.00% 4 Missing ⚠️
superset/daos/chart.py 66.66% 4 Missing ⚠️
...perset/mcp_service/embedded_chart/tool/__init__.py 0.00% 2 Missing ⚠️
superset/mcp_service/app.py 0.00% 1 Missing ⚠️
... and 2 more
Additional details and impacted files
@@             Coverage Diff             @@
##           master   #36933       +/-   ##
===========================================
+ Coverage        0   67.72%   +67.72%     
===========================================
  Files           0      650      +650     
  Lines           0    48261    +48261     
  Branches        0     5251     +5251     
===========================================
+ Hits            0    32687    +32687     
- Misses          0    14292    +14292     
- Partials        0     1282     +1282     
Flag Coverage Δ
hive 42.90% <41.06%> (?)
mysql 65.76% <42.93%> (?)
postgres 65.80% <42.93%> (?)
presto 46.45% <41.60%> (?)
python 67.69% <42.93%> (?)
sqlite 65.52% <42.93%> (?)
unit 100.00% <ø> (?)

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

☔ View full report in Codecov by Sentry.
📢 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.

Copy link
Contributor

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

Choose a reason for hiding this comment

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

Code Review Agent Run #e877b0

Actionable Suggestions - 1
  • superset-frontend/webpack.config.js - 1
Additional Suggestions - 8
  • superset/embedded_chart/api.py - 3
    • API Response Consistency · Line 110-111
      Ensure datasource_id and datasource_type are not null in the JSON response to match the OpenAPI schema, using defaults consistent with GetExplorePermalinkCommand logic.
    • Type Safety Improvement · Line 99-104
      Add type hints to local variables to comply with type safety standards for new Python code. This improves maintainability and aligns with MyPy requirements.
    • Logging Cleanup · Line 118-118
      Remove redundant %s ex from logger.exception, as the method already logs the full traceback and exception details.
  • superset/embedded_chart/exceptions.py - 4
    • Messages not internationalized · Line 21-21
      Exception messages appear to be user-facing and should be internationalized using flask_babel._() for consistency with other Superset exceptions like SupersetMarshmallowValidationError. This ensures messages can be translated if the application supports multiple languages.
    • Missing docstring · Line 20-20
      This new exception class lacks a docstring, which is required for all new classes per the project's coding standards. Consider adding a brief description like 'Raised when an embedded chart permalink is not found or has expired.'
      Code suggestion
       @@ -20,2 +20,3 @@
      - class EmbeddedChartPermalinkNotFoundError(SupersetException):
      -     message = "The embedded chart permalink could not be found or has expired."
      + class EmbeddedChartPermalinkNotFoundError(SupersetException):
      +     """Raised when an embedded chart permalink is not found or has expired."""
      +     message = "The embedded chart permalink could not be found or has expired."
    • Missing docstring · Line 24-24
      This new exception class lacks a docstring, which is required for all new classes per the project's coding standards. Consider adding a brief description like 'Raised when access to an embedded chart is denied.'
      Code suggestion
       @@ -24,2 +24,4 @@
      - class EmbeddedChartAccessDeniedError(SupersetException):
      -     message = "Access to this embedded chart is denied."
      + class EmbeddedChartAccessDeniedError(SupersetException):
      +     """Raised when access to an embedded chart is denied."""
      +     message = "Access to this embedded chart is denied."
    • Missing docstring · Line 28-28
      This new exception class lacks a docstring, which is required for all new classes per the project's coding standards. Consider adding a brief description like 'Raised when the embedded chart feature is disabled.'
  • superset-frontend/src/embeddedChart/index.tsx - 1
    • Inline styles usage · Line 80-80
      The code uses inline styles in several places (e.g., error messages, loading containers, chart wrapper), which may conflict with the guideline to 'avoid custom css and styles' and follow antd best practices whenever possible. While necessary for embedded viewport filling, consider refactoring to use antd's Flex or Space components for layout, or extract to a CSS module if custom styling is unavoidable.
Review Details
  • Files reviewed - 15 · Commit Range: 99b1a97..99b1a97
    • superset-frontend/src/embeddedChart/index.tsx
    • superset-frontend/webpack.config.js
    • superset/config.py
    • superset/embedded_chart/__init__.py
    • superset/embedded_chart/api.py
    • superset/embedded_chart/exceptions.py
    • superset/embedded_chart/view.py
    • superset/initialization/__init__.py
    • superset/mcp_service/app.py
    • superset/mcp_service/embedded_chart/__init__.py
    • superset/mcp_service/embedded_chart/schemas.py
    • superset/mcp_service/embedded_chart/tool/__init__.py
    • superset/mcp_service/embedded_chart/tool/get_embeddable_chart.py
    • superset/security/guest_token.py
    • superset/security/manager.py
  • Files skipped - 0
  • Tools
    • Eslint (Linter) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

@aminghadersohi
Copy link
Contributor Author

Code Review Responses

✅ Fixed Issues

Comment Fix
Null pointer in validateMessageEvent Added null check: if (data == null || typeof data !== 'object' || data.type !== MESSAGE_TYPE)
Race condition with started flag Now sets started = true before start() and resets to false on failure
Security: exception message leak in 500 Returns generic response_500() without exposing exception message
Exception chaining leaks internal details Removed from ex, re-raises directly or creates new instance
Missing docstrings in exceptions Added docstrings to all exception classes

❌ Not Applicable / Incorrect Suggestions

Suggestion Reason
GUEST_TOKEN_HEADER_NAME KeyError Config value exists in default config.py (line 2121). Existing embedded/view.py uses same pattern.
Webpack path format The leading slash format matches existing spa and embedded entries which work correctly.
Feature flag confusion No EMBEDDABLE_CHARTS flag exists - only EMBEDDED_SUPERSET. The new EMBEDDABLE_CHARTS_MCP is intentionally separate.
Lazy import in init.py Follows existing pattern used throughout the MCP service codebase.
ttl_minutes None check Pydantic model provides default=60, so value is never None.
Import style in app.py Follows existing pattern for other tool imports in the file.

Copy link
Contributor

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

Choose a reason for hiding this comment

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

Code Review Agent Run #a3d995

Actionable Suggestions - 1
  • superset/security/manager.py - 1
Additional Suggestions - 2
  • superset-frontend/src/embeddedChart/index.tsx - 2
    • Improved null safety · Line 125-126
      The added null check for event.data prevents potential TypeError if data is null/undefined, aligning with TypeScript best practices for MessageEvent handling.
    • Enhanced error handling · Line 292-298
      Wrapping start() in .catch() handles async failures gracefully, logging errors and resetting state, which improves reliability for embedded chart initialization.
Review Details
  • Files reviewed - 16 · Commit Range: 99b1a97..4be0466
    • superset-frontend/src/embeddedChart/index.tsx
    • superset-frontend/webpack.config.js
    • superset/config.py
    • superset/embedded_chart/__init__.py
    • superset/embedded_chart/api.py
    • superset/embedded_chart/exceptions.py
    • superset/embedded_chart/view.py
    • superset/initialization/__init__.py
    • superset/mcp_service/app.py
    • superset/mcp_service/embedded_chart/__init__.py
    • superset/mcp_service/embedded_chart/schemas.py
    • superset/mcp_service/embedded_chart/tool/__init__.py
    • superset/mcp_service/embedded_chart/tool/get_embeddable_chart.py
    • superset/security/guest_token.py
    • superset/security/manager.py
    • tests/integration_tests/security_tests.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

@bito-code-review
Copy link
Contributor

bito-code-review bot commented Jan 7, 2026

Code Review Agent Run #86accd

Actionable Suggestions - 0
Review Details
  • Files reviewed - 16 · Commit Range: 4be0466..fb7714c
    • superset-frontend/src/embeddedChart/index.tsx
    • superset-frontend/webpack.config.js
    • superset/config.py
    • superset/embedded_chart/__init__.py
    • superset/embedded_chart/api.py
    • superset/embedded_chart/exceptions.py
    • superset/embedded_chart/view.py
    • superset/initialization/__init__.py
    • superset/mcp_service/app.py
    • superset/mcp_service/embedded_chart/__init__.py
    • superset/mcp_service/embedded_chart/schemas.py
    • superset/mcp_service/embedded_chart/tool/__init__.py
    • superset/mcp_service/embedded_chart/tool/get_embeddable_chart.py
    • superset/security/guest_token.py
    • superset/security/manager.py
    • tests/integration_tests/security_tests.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

@bito-code-review
Copy link
Contributor

bito-code-review bot commented Jan 7, 2026

Code Review Agent Run #0b3e6d

Actionable Suggestions - 0
Review Details
  • Files reviewed - 16 · Commit Range: fb7714c..c1ca010
    • superset-frontend/src/embeddedChart/index.tsx
    • superset-frontend/webpack.config.js
    • superset/config.py
    • superset/embedded_chart/__init__.py
    • superset/embedded_chart/api.py
    • superset/embedded_chart/exceptions.py
    • superset/embedded_chart/view.py
    • superset/initialization/__init__.py
    • superset/mcp_service/app.py
    • superset/mcp_service/embedded_chart/__init__.py
    • superset/mcp_service/embedded_chart/schemas.py
    • superset/mcp_service/embedded_chart/tool/__init__.py
    • superset/mcp_service/embedded_chart/tool/get_embeddable_chart.py
    • superset/security/guest_token.py
    • superset/security/manager.py
    • tests/integration_tests/security_tests.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

@codeant-ai-for-open-source
Copy link
Contributor

CodeAnt AI is running Incremental review


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@bito-code-review
Copy link
Contributor

bito-code-review bot commented Jan 7, 2026

Code Review Agent Run #42298f

Actionable Suggestions - 0
Additional Suggestions - 1
  • superset/embedded_chart/view.py - 1
    • Config access inconsistency · Line 58-60
      The change to use .get() with a default for GUEST_TOKEN_HEADER_NAME is a good defensive practice, preventing potential KeyError if the config key is missing. However, similar bootstrap code in superset/embedded/view.py still uses direct access, creating inconsistency that could lead to errors in edge cases where config isn't fully loaded.
Review Details
  • Files reviewed - 16 · Commit Range: c1ca010..d87b9c7
    • superset-frontend/src/embeddedChart/index.tsx
    • superset-frontend/webpack.config.js
    • superset/config.py
    • superset/embedded_chart/__init__.py
    • superset/embedded_chart/api.py
    • superset/embedded_chart/exceptions.py
    • superset/embedded_chart/view.py
    • superset/initialization/__init__.py
    • superset/mcp_service/app.py
    • superset/mcp_service/embedded_chart/__init__.py
    • superset/mcp_service/embedded_chart/schemas.py
    • superset/mcp_service/embedded_chart/tool/__init__.py
    • superset/mcp_service/embedded_chart/tool/get_embeddable_chart.py
    • superset/security/guest_token.py
    • superset/security/manager.py
    • tests/integration_tests/security_tests.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

@codeant-ai-for-open-source
Copy link
Contributor

CodeAnt AI is running Incremental review


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@bito-code-review
Copy link
Contributor

bito-code-review bot commented Jan 7, 2026

Code Review Agent Run #ee1305

Actionable Suggestions - 0
Review Details
  • Files reviewed - 58 · Commit Range: 72622ec..e18805c
    • Dockerfile
    • docs/docs/api.mdx
    • docs/docs/configuration/alerts-reports.mdx
    • docs/docs/configuration/async-queries-celery.mdx
    • docs/docs/configuration/cache.mdx
    • docs/docs/configuration/configuring-superset.mdx
    • docs/docs/configuration/databases.mdx
    • docs/docs/configuration/sql-templating.mdx
    • docs/docs/configuration/theming.mdx
    • docs/docs/contributing/contributing.mdx
    • docs/docs/contributing/development.mdx
    • docs/docs/installation/kubernetes.mdx
    • docs/docs/quickstart.mdx
    • docs/docs/security/securing_superset.mdx
    • docs/docs/using-superset/creating-your-first-dashboard.mdx
    • docs/docs/using-superset/exploring-data.mdx
    • docs/docusaurus.config.ts
    • docs/src/styles/custom.css
    • docs/src/theme/Admonition/Types.js
    • superset-frontend/packages/superset-core/src/api/environment.ts
    • superset-frontend/packages/superset-core/src/api/index.ts
    • superset-frontend/packages/superset-core/src/api/sqlLab.ts
    • superset-frontend/plugins/plugin-chart-ag-grid-table/src/utils/dateFilterComparator.ts
    • superset-frontend/plugins/plugin-chart-ag-grid-table/test/utils/dateFilterComparator.test.ts
    • superset-frontend/src/core/authentication/index.ts
    • superset-frontend/src/core/commands/index.ts
    • superset-frontend/src/core/environment/index.ts
    • superset-frontend/src/core/extensions/index.ts
    • superset-frontend/src/core/index.ts
    • superset-frontend/src/core/sqlLab/index.ts
    • superset-frontend/src/embeddedChart/index.tsx
    • superset-frontend/src/extensions/ExtensionsStartup.test.tsx
    • superset-frontend/src/extensions/ExtensionsStartup.tsx
    • superset-frontend/webpack.config.js
    • superset/commands/report/alert.py
    • superset/commands/report/execute.py
    • superset/config.py
    • superset/embedded_chart/__init__.py
    • superset/embedded_chart/api.py
    • superset/embedded_chart/exceptions.py
    • superset/embedded_chart/view.py
    • superset/initialization/__init__.py
    • superset/jinja_context.py
    • superset/mcp_service/app.py
    • superset/mcp_service/embedded_chart/__init__.py
    • superset/mcp_service/embedded_chart/schemas.py
    • superset/mcp_service/embedded_chart/tool/__init__.py
    • superset/mcp_service/embedded_chart/tool/get_embeddable_chart.py
    • superset/security/guest_token.py
    • superset/security/manager.py
    • superset/sqllab/query_render.py
    • superset/views/datasource/utils.py
    • tests/integration_tests/reports/alert_tests.py
    • tests/integration_tests/security_tests.py
    • tests/unit_tests/commands/report/alert_test.py
    • tests/unit_tests/jinja_context_test.py
    • tests/unit_tests/views/datasource/__init__.py
    • tests/unit_tests/views/datasource/utils_test.py
  • Files skipped - 5
    • .github/workflows/docker.yml - Reason: Filter setting
    • docs/developer_portal/extensions/architecture.md - Reason: Filter setting
    • docs/developer_portal/extensions/development.md - Reason: Filter setting
    • superset-frontend/package-lock.json - Reason: Filter setting
    • superset-frontend/packages/superset-core/package.json - Reason: Filter setting
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

@aminghadersohi
Copy link
Contributor Author

We have lots of FFs

+1 If we can avoid a feature flag it would be better.

yeah you're both 100% right. let me get rid of it

@codeant-ai-for-open-source
Copy link
Contributor

CodeAnt AI is running Incremental review


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@bito-code-review
Copy link
Contributor

bito-code-review bot commented Jan 8, 2026

Code Review Agent Run #8c50b8

Actionable Suggestions - 0
Additional Suggestions - 1
  • superset/embedded_chart/view.py - 1
    • Inconsistent Feature Flag Usage · Line 49-49
      The feature flag check for EMBEDDED_SUPERSET has been removed, making embedded charts always accessible regardless of the flag setting. This appears inconsistent with other embedded views like superset/embedded/view.py and superset/embedded/api.py, which still enforce the flag. If the flag is intended to gate all embedded functionality, this could allow unintended access when the feature is disabled.
Review Details
  • Files reviewed - 57 · Commit Range: e18805c..0b1d160
    • Dockerfile
    • docs/docs/api.mdx
    • docs/docs/configuration/alerts-reports.mdx
    • docs/docs/configuration/async-queries-celery.mdx
    • docs/docs/configuration/cache.mdx
    • docs/docs/configuration/configuring-superset.mdx
    • docs/docs/configuration/databases.mdx
    • docs/docs/configuration/sql-templating.mdx
    • docs/docs/configuration/theming.mdx
    • docs/docs/contributing/contributing.mdx
    • docs/docs/contributing/development.mdx
    • docs/docs/installation/kubernetes.mdx
    • docs/docs/quickstart.mdx
    • docs/docs/security/securing_superset.mdx
    • docs/docs/using-superset/creating-your-first-dashboard.mdx
    • docs/docs/using-superset/exploring-data.mdx
    • docs/docusaurus.config.ts
    • docs/src/styles/custom.css
    • docs/src/theme/Admonition/Types.js
    • superset-frontend/packages/superset-core/src/api/environment.ts
    • superset-frontend/packages/superset-core/src/api/index.ts
    • superset-frontend/packages/superset-core/src/api/sqlLab.ts
    • superset-frontend/plugins/plugin-chart-ag-grid-table/src/utils/dateFilterComparator.ts
    • superset-frontend/plugins/plugin-chart-ag-grid-table/test/utils/dateFilterComparator.test.ts
    • superset-frontend/src/core/authentication/index.ts
    • superset-frontend/src/core/commands/index.ts
    • superset-frontend/src/core/environment/index.ts
    • superset-frontend/src/core/extensions/index.ts
    • superset-frontend/src/core/index.ts
    • superset-frontend/src/core/sqlLab/index.ts
    • superset-frontend/src/embeddedChart/index.tsx
    • superset-frontend/src/extensions/ExtensionsStartup.test.tsx
    • superset-frontend/src/extensions/ExtensionsStartup.tsx
    • superset-frontend/webpack.config.js
    • superset/commands/report/alert.py
    • superset/commands/report/execute.py
    • superset/embedded_chart/__init__.py
    • superset/embedded_chart/api.py
    • superset/embedded_chart/exceptions.py
    • superset/embedded_chart/view.py
    • superset/initialization/__init__.py
    • superset/jinja_context.py
    • superset/mcp_service/app.py
    • superset/mcp_service/embedded_chart/__init__.py
    • superset/mcp_service/embedded_chart/schemas.py
    • superset/mcp_service/embedded_chart/tool/__init__.py
    • superset/mcp_service/embedded_chart/tool/get_embeddable_chart.py
    • superset/security/guest_token.py
    • superset/security/manager.py
    • superset/sqllab/query_render.py
    • superset/views/datasource/utils.py
    • tests/integration_tests/reports/alert_tests.py
    • tests/integration_tests/security_tests.py
    • tests/unit_tests/commands/report/alert_test.py
    • tests/unit_tests/jinja_context_test.py
    • tests/unit_tests/views/datasource/__init__.py
    • tests/unit_tests/views/datasource/utils_test.py
  • Files skipped - 5
    • .github/workflows/docker.yml - Reason: Filter setting
    • docs/developer_portal/extensions/architecture.md - Reason: Filter setting
    • docs/developer_portal/extensions/development.md - Reason: Filter setting
    • superset-frontend/package-lock.json - Reason: Filter setting
    • superset-frontend/packages/superset-core/package.json - Reason: Filter setting
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

@codeant-ai-for-open-source
Copy link
Contributor

CodeAnt AI is running Incremental review


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

Add a new MCP tool `get_embeddable_chart` that enables AI agents to create
ephemeral chart visualizations with guest token authentication. This allows
charts to be embedded in external applications (Claude Desktop, ChatGPT, etc.)
without persisting them to the database.

Key changes:
- Add CHART_PERMALINK resource type to GuestTokenResourceType enum
- Add validation for chart_permalink resources in SecurityManager
- Add EMBEDDABLE_CHARTS_MCP feature flag (disabled by default)
- Create embedded_chart backend module with API and view
- Create MCP tool with schemas for get_embeddable_chart
- Create frontend embeddedChart entry using StatefulChart component

The feature uses the existing permalink system for chart state storage
with TTL support, and leverages StatefulChart for lightweight rendering
that handles data fetching internally.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

fix: address CI failures for embeddable charts PR

- Remove literal color apache#666 from embeddedChart (use default text color)
- Shorten long description lines in schemas.py
- Fix import ordering in app.py
- Add EmbeddedChartRestApi and EmbeddedChartView to security allowlist

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

fix: address code review feedback for embeddable charts

- Fix null pointer in validateMessageEvent (typeof null === 'object')
- Fix race condition with started flag - reset on failure
- Fix security issue - don't leak exception message in 500 response
- Add docstrings to exception classes
- Remove redundant %s formatting in logger.exception

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

fix: remove exception chaining to prevent internal detail leakage

Remove `from ex` in exception handling to prevent leaking internal
exception details. Re-raise EmbeddedChartPermalinkNotFoundError directly
if already raised, otherwise raise a new instance without chaining.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

fix: use 'from None' to satisfy ruff B904 rule

Within an except clause, using 'from None' explicitly
suppresses exception chaining which prevents internal
error details from being exposed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

chore: format with ruff 0.9.7

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

chore: format embeddedChart with prettier

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

fix: add proper type annotations for mypy compliance

- Import GuestTokenUser, GuestTokenResource, GuestTokenRlsRule types
- Add type annotations to guest_user, resources, rls_rules
- Use GuestTokenResourceType enum directly instead of .value
- Handle bytes return type from create_guest_access_token

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

fix: use .get() for GUEST_TOKEN_HEADER_NAME config access

Provides a default value to prevent potential KeyError.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

chore: re-trigger CI for flaky test

The sharded-jest-tests (3) failure is a flaky test timeout
(DatasourceEditor.test.tsx) unrelated to this PR's changes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

fix(mcp): add referrer validation and @Protect() decorator for embeddable charts

Security improvements based on code review comparing with dashboard embedding:

1. Add optional allowed_domains parameter to get_embeddable_chart MCP tool
   - Stored in permalink state for later validation
   - Allows restricting which domains can embed the chart

2. Add referrer validation to EmbeddedChartView
   - Validates request.referrer against allowed_domains
   - Uses same same_origin() check as dashboard embedding
   - Returns 403 if referrer not in allowed domains list

3. Add @Protect() decorator to EmbeddedChartRestApi.get()
   - Consistent with EmbeddedDashboardRestApi pattern
   - Adds class_permission_name for FAB permissions

4. Include allowed_domains in API response
   - Useful for debugging and validation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

chore: re-trigger CI for flaky test

The sharded-jest-tests (3) failure is a flaky test timeout
(DatasourceEditor.test.tsx) unrelated to this PR's changes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

fix(mcp): fix API response format and PyJWT compatibility for embeddable charts

1. Fix API response format to match frontend expectations:
   - Frontend expects { state: { formData: {...} } }
   - Was returning { result: { form_data: {...} } }
   - Now returns state directly from permalink

2. Fix PyJWT compatibility:
   - PyJWT 2.0+ returns string, older versions return bytes
   - Handle both cases when decoding guest token

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

fix(mcp): add guest token security for embedded chart data access

- Add guest token validation in embedded_chart API to verify permalink access
- Add has_guest_chart_permalink_access() to security manager to allow
  guest users with chart_permalink resources to access datasources
- Add can_read CurrentUserRestApi to PUBLIC_ROLE_PERMISSIONS for
  frontend initialization in embedded views
- Remove redundant referrer validation from view (now handled by guest token)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

fix(mcp): remove EMBEDDABLE_CHARTS_MCP feature flag, use EMBEDDED_SUPERSET

Per PR review feedback, avoid adding a new feature flag since MCP is
already feature-flagged. Embedded charts now use the existing
EMBEDDED_SUPERSET flag which is consistent with dashboard embedding.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

fix(mcp): remove all feature flag checks from embedded charts

Per PR review feedback, remove all feature flag usage. The embedded
chart functionality is now always available - no feature flags needed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

fix(mcp): add isinstance check for GuestUser in has_guest_chart_permalink_access

The method was failing for regular User objects that don't have a
resources attribute. Added explicit isinstance(user, GuestUser) check
to ensure we only access user.resources for actual GuestUser instances.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

fix(mcp): fix ruff linting issues in embedded chart files

- Fix import sorting in api.py
- Remove unused imports in view.py (Any, cast, same_origin, GetExplorePermalinkCommand)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@aminghadersohi aminghadersohi force-pushed the amin/embeddable-charts-mcp branch from e07f57d to ccb0742 Compare January 8, 2026 15:45
@github-actions github-actions bot removed doc Namespace | Anything related to documentation plugins dependencies:npm github_actions Pull requests that update GitHub Actions code packages labels Jan 8, 2026
Copy link
Contributor

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

Choose a reason for hiding this comment

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

Code Review Agent Run #68cad7

Actionable Suggestions - 1
  • superset/security/manager.py - 1
Additional Suggestions - 2
  • superset-frontend/src/embeddedChart/index.tsx - 2
    • Unchecked DOM element access · Line 76-76
      The code asserts appMountPoint is non-null with `!`, but if `document.getElementById('app')` returns null, this will cause a runtime TypeError. In an embedded context, the element should exist, but adding a check improves robustness.
      Code suggestion
       diff --git a/superset-frontend/src/embeddedChart/index.tsx b/superset-frontend/src/embeddedChart/index.tsx
       index 0000000..1234567 100644
      --- a/superset-frontend/src/embeddedChart/index.tsx
      +++ b/superset-frontend/src/embeddedChart/index.tsx
       @@ -75,7 +75,9 @@ interface PermalinkState {
          formData: QueryFormData;
        }
       
      -const appMountPoint = document.getElementById('app')!;
      +const appMountPoint = document.getElementById('app');
      +if (!appMountPoint) {
      +  throw new Error('App mount point element not found');
      +}
       
        const MESSAGE_TYPE = '__embedded_comms__';
       
        function showFailureMessage(message: string) {
    • Potential XSS via innerHTML · Line 80-80
      Using innerHTML to inject content poses XSS risks, even if the message is from a translation function. Switch to creating DOM elements programmatically for safer content insertion.
Review Details
  • Files reviewed - 15 · Commit Range: ccb0742..ccb0742
    • superset-frontend/src/embeddedChart/index.tsx
    • superset-frontend/webpack.config.js
    • superset/embedded_chart/__init__.py
    • superset/embedded_chart/api.py
    • superset/embedded_chart/exceptions.py
    • superset/embedded_chart/view.py
    • superset/initialization/__init__.py
    • superset/mcp_service/app.py
    • superset/mcp_service/embedded_chart/__init__.py
    • superset/mcp_service/embedded_chart/schemas.py
    • superset/mcp_service/embedded_chart/tool/__init__.py
    • superset/mcp_service/embedded_chart/tool/get_embeddable_chart.py
    • superset/security/guest_token.py
    • superset/security/manager.py
    • tests/integration_tests/security_tests.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

Comment on lines +2854 to +2855
except Exception:
raise EmbeddedChartPermalinkNotFoundError() from None
Copy link
Contributor

Choose a reason for hiding this comment

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

Blind exception catch too broad

Replace the broad except Exception on line 2854 with specific exception types. Catch only EmbeddedChartPermalinkNotFoundError or other expected exceptions to avoid masking unexpected errors.

Code suggestion
Check the AI-generated fix before applying
Suggested change
except Exception:
raise EmbeddedChartPermalinkNotFoundError() from None
except (EmbeddedChartPermalinkNotFoundError, ValueError, KeyError):
raise EmbeddedChartPermalinkNotFoundError() from None

Code Review Run #68cad7


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

Add "Embed chart" option to chart header dropdown menu on dashboards.
When clicked, opens a modal that generates embed code (iframe + guest token)
using the existing permalink + guest token infrastructure.

Changes:
- Add POST /api/v1/embedded_chart/ endpoint to create embeddable charts
- Add EmbeddedChartModal component with allowed domains and TTL settings
- Add "Embed chart" menu item to SliceHeaderControls
- Add EmbedChart to MenuKeys enum

This brings UI parity with PR apache#33424's approach while using our simpler
ephemeral permalink-based architecture (no database model needed).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Copy link
Contributor

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

Choose a reason for hiding this comment

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

Code Review Agent Run #e87f28

Actionable Suggestions - 1
  • superset/embedded_chart/api.py - 1
Additional Suggestions - 2
  • superset/embedded_chart/api.py - 1
    • Unbounded Input · Line 239-239
      ttl_minutes lacks bounds checking, allowing negative values (past expiration) or very large ones. Add min/max validation to ensure reasonable embed lifetimes.
  • superset-frontend/src/dashboard/components/EmbeddedChartModal/index.tsx - 1
    • Script Injection Risk · Line 119-120
      The inline script embeds guest_token and iframe_url directly in template literals, which could break if these values contain single quotes. Use JSON.stringify to safely escape them.
Review Details
  • Files reviewed - 18 · Commit Range: ccb0742..2b4b4f8
    • superset-frontend/src/dashboard/components/EmbeddedChartModal/index.tsx
    • superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx
    • superset-frontend/src/dashboard/types.ts
    • superset-frontend/src/embeddedChart/index.tsx
    • superset-frontend/webpack.config.js
    • superset/embedded_chart/__init__.py
    • superset/embedded_chart/api.py
    • superset/embedded_chart/exceptions.py
    • superset/embedded_chart/view.py
    • superset/initialization/__init__.py
    • superset/mcp_service/app.py
    • superset/mcp_service/embedded_chart/__init__.py
    • superset/mcp_service/embedded_chart/schemas.py
    • superset/mcp_service/embedded_chart/tool/__init__.py
    • superset/mcp_service/embedded_chart/tool/get_embeddable_chart.py
    • superset/security/guest_token.py
    • superset/security/manager.py
    • tests/integration_tests/security_tests.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

allowed_domains: list[str] = body.get("allowed_domains", [])
ttl_minutes: int = body.get("ttl_minutes", 60)

if not form_data:
Copy link
Contributor

Choose a reason for hiding this comment

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

Input Validation Gap

The code checks if form_data is truthy but doesn't validate its structure. Since CreateExplorePermalinkCommand expects 'datasource' in formData, invalid input could cause runtime exceptions. Add early validation to prevent this.

Code Review Run #e87f28


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

Add CORS/referrer validation to embedded chart view, matching the
dashboard embedding behavior. If allowed_domains is configured in
the permalink state, validate that the request referrer matches
one of the allowed domains before rendering.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@codeant-ai-for-open-source
Copy link
Contributor

CodeAnt AI is running Incremental review


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

Copy link
Contributor

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

Choose a reason for hiding this comment

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

Code Review Agent Run #b9e5b1

Actionable Suggestions - 1
  • superset/embedded_chart/view.py - 1
    • Security Bug in Referrer Validation · Line 42-53
Review Details
  • Files reviewed - 18 · Commit Range: 2b4b4f8..1e6c4ee
    • superset-frontend/src/dashboard/components/EmbeddedChartModal/index.tsx
    • superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx
    • superset-frontend/src/dashboard/types.ts
    • superset-frontend/src/embeddedChart/index.tsx
    • superset-frontend/webpack.config.js
    • superset/embedded_chart/__init__.py
    • superset/embedded_chart/api.py
    • superset/embedded_chart/exceptions.py
    • superset/embedded_chart/view.py
    • superset/initialization/__init__.py
    • superset/mcp_service/app.py
    • superset/mcp_service/embedded_chart/__init__.py
    • superset/mcp_service/embedded_chart/schemas.py
    • superset/mcp_service/embedded_chart/tool/__init__.py
    • superset/mcp_service/embedded_chart/tool/get_embeddable_chart.py
    • superset/security/guest_token.py
    • superset/security/manager.py
    • tests/integration_tests/security_tests.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

Comment on lines +42 to +53
def same_origin(url1: str | None, url2: str | None) -> bool:
"""Check if two URLs have the same origin (scheme + netloc)."""
if not url1 or not url2:
return False
parsed1 = urlparse(url1)
parsed2 = urlparse(url2)
# For domain matching, we just check if the host matches
# url2 might just be a domain like "example.com"
if not parsed2.scheme:
# url2 is just a domain, check if it matches url1's netloc
return parsed1.netloc == url2 or parsed1.netloc.endswith(f".{url2}")
return (parsed1.scheme, parsed1.netloc) == (parsed2.scheme, parsed2.netloc)
Copy link
Contributor

Choose a reason for hiding this comment

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

Security Bug in Referrer Validation

The same_origin function incorrectly uses netloc (which includes ports) for domain matching, causing it to reject valid referrers with non-standard ports like 'https://example.com:8080' when 'example.com' is allowed. It should use hostname for host-only comparison and perform case-insensitive matching, as hosts are case-insensitive per RFC.

Code Review Run #b9e5b1


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

- Remove CodeBlock styled component using deprecated theme.colors
- Change CodeOutlined icon to ExportOutlined (valid icon)
- Add chartId prop to EmbeddedChartModal
- Simplify EmbeddedChartModal to use existing embedded chart API
- Fix ESLint issues (duplicate imports, destructuring, useEffect pattern)
- Replace console.error with logging.error

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@codeant-ai-for-open-source
Copy link
Contributor

CodeAnt AI is running Incremental review


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@github-actions github-actions bot added the risk:db-migration PRs that require a DB migration label Jan 9, 2026
aminghadersohi and others added 4 commits January 8, 2026 23:07
Add new embedded chart permissions to the expected permissions set in
test_info_security_chart test.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
The Embed code option (simple iframe URL) was previously always available
with EMBEDDABLE_CHARTS: True by default. Keep it always visible since it's
a simple feature. Only gate the new Embed chart option (which uses guest
tokens) behind the EMBEDDED_SUPERSET feature flag.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Revert to using EMBEDDABLE_CHARTS instead of EMBEDDED_SUPERSET for
chart embedding features to maintain backwards compatibility.

- EMBEDDABLE_CHARTS: True by default (for Embed code/chart options)
- EMBEDDED_SUPERSET: False by default (for dashboard embedding with guest tokens)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Copy link
Contributor

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

Choose a reason for hiding this comment

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

Code Review Agent Run #4834de

Actionable Suggestions - 3
  • superset/config.py - 1
  • superset-frontend/src/dashboard/components/EmbeddedChartModal/index.tsx - 1
  • superset/charts/api.py - 1
Additional Suggestions - 9
  • tests/integration_tests/charts/api_tests.py - 1
    • Unrestricted embedded permissions · Line 309-312
      These embedded permissions are added to the expected set, but unlike "can_set_embedded", they are not restricted in the security manager. This could allow unauthorized access to embedded configurations. Consider adding them to ADMIN_ONLY_PERMISSIONS to match the pattern for admin-only features.
  • superset/charts/api.py - 1
    • Incomplete Transaction Handling · Line 1320-1339
      The try block only catches ValidationError from schema load, but if EmbeddedChartDAO.upsert raises an exception, the session won't rollback, risking partial DB commits.
  • superset/daos/chart.py - 1
    • Type Hint Error · Line 128-128
      The type hint for 'item' in the create method appears incorrect, as it references the DAO class rather than the model type expected by BaseDAO[EmbeddedChart]. This could cause MyPy type checking failures, though it won't affect runtime since the method raises NotImplementedError.
      Code suggestion
       @@ -128,1 +128,1 @@
      -item: EmbeddedChartDAO | None = None,
      +item: EmbeddedChart | None = None,
  • superset/models/embedded_chart.py - 1
    • Property logic refinement · Line 53-58
      The `allowed_domains` property could include empty strings if `allow_domain_list` has consecutive commas or leading/trailing commas, which might cause unexpected behavior in embedding checks. Consider refining the logic to handle malformed input gracefully.
      Code suggestion
       @@ -53,6 +53,6 @@
            @property
            def allowed_domains(self) -> list[str]:
                """
                A list of domains which are allowed to embed the chart.
                An empty list means any domain can embed.
                """
      -        return self.allow_domain_list.split(",") if self.allow_domain_list else []
      +        return [domain.strip() for domain in self.allow_domain_list.split(",") if domain.strip()] if self.allow_domain_list else []
  • superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx - 1
    • Icon choice for embed menu item · Line 501-501
      The icon for the 'Embed chart' menu item was changed to ExportOutlined, but embedding charts typically involves code generation, so CodeOutlined is more appropriate.
      Code suggestion
       @@ -501,1 +501,1 @@
      -      icon: <Icons.ExportOutlined css={dropdownIconsStyles} />,
      +      icon: <Icons.CodeOutlined css={dropdownIconsStyles} />,
  • superset/views/embedded_charts.py - 1
    • Missing Documentation · Line 33-33
      The list method is missing a docstring. Per the project's coding standards in AGENTS.md and .cursor/rules/dev-standard.mdc, docstrings are required for new functions and methods to improve maintainability.
      Code suggestion
       @@ -31,6 +31,7 @@
            @expose("/list/")
            @has_access
            def list(self) -> FlaskResponse:
      +        """Render the embedded charts list page."""
                return super().render_app_template()
  • superset/initialization/__init__.py - 1
    • Category Mismatch · Line 526-533
      The category "Security" may not fit for EmbeddedChartsView, as it's chart management rather than security. Other chart views like SliceModelView use no category. If embedding has security implications, keep as is.
  • superset/commands/chart/delete.py - 1
    • Code Structure Inconsistency · Line 81-81
      The run method here returns the result of EmbeddedChartDAO.delete, but the similar DeleteChartCommand.run method in the same file does not return. For consistency within the codebase, consider removing the return statement.
  • superset/charts/schemas.py - 1
    • Schema metadata suggestion · Line 348-356
      The new EmbeddedChartConfigSchema and EmbeddedChartResponseSchema classes are correctly defined with appropriate field types and requirements that match their usage in the charts API. However, consider adding metadata to the fields for better OpenAPI documentation, as seen in other schemas in this file.
Review Details
  • Files reviewed - 37 · Commit Range: 1e6c4ee..66ad889
    • superset-frontend/src/dashboard/components/EmbeddedChartModal/index.tsx
    • superset-frontend/src/dashboard/components/SliceHeaderControls/SliceHeaderControls.test.tsx
    • superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx
    • superset-frontend/src/dashboard/components/menu/ShareMenuItems/ShareMenuItems.test.tsx
    • superset-frontend/src/dashboard/components/menu/ShareMenuItems/index.tsx
    • superset-frontend/src/dashboard/types.ts
    • superset-frontend/src/embeddedChart/index.tsx
    • superset-frontend/src/explore/components/ExploreChartHeader/ExploreChartHeader.test.tsx
    • superset-frontend/src/explore/components/ExploreChartHeader/index.jsx
    • superset-frontend/src/explore/components/useExploreAdditionalActionsMenu/index.jsx
    • superset-frontend/src/pages/EmbeddedChartsList/index.tsx
    • superset-frontend/src/views/routes.tsx
    • superset-frontend/webpack.config.js
    • superset/charts/api.py
    • superset/charts/schemas.py
    • superset/commands/chart/delete.py
    • superset/commands/chart/exceptions.py
    • superset/config.py
    • superset/daos/chart.py
    • superset/embedded_chart/__init__.py
    • superset/embedded_chart/api.py
    • superset/embedded_chart/exceptions.py
    • superset/embedded_chart/view.py
    • superset/initialization/__init__.py
    • superset/mcp_service/app.py
    • superset/mcp_service/embedded_chart/__init__.py
    • superset/mcp_service/embedded_chart/schemas.py
    • superset/mcp_service/embedded_chart/tool/__init__.py
    • superset/mcp_service/embedded_chart/tool/get_embeddable_chart.py
    • superset/migrations/versions/2026-01-08_16-45_50aff65919a0_add_embedded_charts_table.py
    • superset/models/embedded_chart.py
    • superset/models/slice.py
    • superset/security/guest_token.py
    • superset/security/manager.py
    • superset/views/embedded_charts.py
    • tests/integration_tests/charts/api_tests.py
    • tests/integration_tests/security_tests.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

Comment on lines 594 to 595
# Enable caching per user key for Superset cache (not database cache impersonation)
"CACHE_QUERY_BY_USER": False,
Copy link
Contributor

Choose a reason for hiding this comment

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

Breaking change in stable feature flag

Removing the stable EMBEDDABLE_CHARTS feature flag from DEFAULT_FEATURE_FLAGS disables chart embedding by default, which is a breaking change for users relying on the default configuration. According to FEATURE_FLAGS.md and official docs, this flag is still stable and not deprecated. If this removal is intentional, consider adding a deprecation notice first.

Code Review Run #4834de


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

Comment on lines 142 to 146
.then(({ result }) => {
setReady(true);
setEmbedded(result);
setAllowedDomains(result ? result.allowed_domains.join(', ') : '');
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Error Handling Issue

The useEffect fails to set ready to true on API errors, potentially leaving the component stuck in loading state. Add a .finally block to ensure ready is always set.

Code suggestion
Check the AI-generated fix before applying
 @@ -141,6 +141,7 @@
        .then(({ result }) => {
          setReady(true);
          setEmbedded(result);
          setAllowedDomains(result ? result.allowed_domains.join(', ') : '');
        })
 +      .finally(() => setReady(true));
 

Code Review Run #4834de


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

Comment on lines 1247 to 1339
@expose("/<id_or_uuid>/embedded", methods=["POST", "PUT"])
@protect()
@safe
@statsd_metrics
@event_logger.log_this_with_context(
action=lambda self, *args, **kwargs: f"{self.__class__.__name__}.set_embedded",
log_to_statsd=False,
)
def set_embedded(self, id_or_uuid: str) -> Response:
"""Set a chart's embedded configuration.
---
post:
summary: Set a chart's embedded configuration
parameters:
- in: path
schema:
type: string
name: id_or_uuid
description: The chart id or uuid
requestBody:
description: The embedded configuration to set
required: true
content:
application/json:
schema: EmbeddedChartConfigSchema
responses:
200:
description: Successfully set the configuration
content:
application/json:
schema:
type: object
properties:
result:
$ref: '#/components/schemas/EmbeddedChartResponseSchema'
401:
$ref: '#/components/responses/401'
404:
$ref: '#/components/responses/404'
500:
$ref: '#/components/responses/500'
put:
description: >-
Sets a chart's embedded configuration.
parameters:
- in: path
schema:
type: string
name: id_or_uuid
description: The chart id or uuid
requestBody:
description: The embedded configuration to set
required: true
content:
application/json:
schema: EmbeddedChartConfigSchema
responses:
200:
description: Successfully set the configuration
content:
application/json:
schema:
type: object
properties:
result:
$ref: '#/components/schemas/EmbeddedChartResponseSchema'
401:
$ref: '#/components/responses/401'
404:
$ref: '#/components/responses/404'
500:
$ref: '#/components/responses/500'
"""
try:
chart = ChartDAO.get_by_id_or_uuid(id_or_uuid)
except ChartNotFoundError:
return self.response_404()

try:
body = self.embedded_config_schema.load(request.json)

embedded = EmbeddedChartDAO.upsert(
chart,
body["allowed_domains"],
)
db.session.commit() # pylint: disable=consider-using-transaction

result = self.embedded_response_schema.dump(embedded)
return self.response(200, result=result)
except ValidationError as error:
db.session.rollback() # pylint: disable=consider-using-transaction
return self.response_400(message=error.messages)

Copy link
Contributor

Choose a reason for hiding this comment

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

Missing Permission Decorator

The set_embedded endpoint lacks a @permission_name decorator, unlike get_embedded ('read') and delete_embedded ('set_embedded'). This could allow unauthorized config changes if permissions aren't enforced elsewhere.

Citations

Code Review Run #4834de


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

@bito-code-review
Copy link
Contributor

bito-code-review bot commented Jan 9, 2026

Code Review Agent Run #d77337

Actionable Suggestions - 0
Additional Suggestions - 5
  • superset-frontend/src/dashboard/components/menu/ShareMenuItems/ShareMenuItems.test.tsx - 5
    • Feature flag consistency · Line 226-226
      This change updates the feature flag from EMBEDDED_SUPERSET to EMBEDDABLE_CHARTS to match the component's usage of FeatureFlag.EmbeddableCharts, ensuring tests correctly enable the embed code functionality.
    • Feature flag consistency · Line 251-251
      This change updates the feature flag from EMBEDDED_SUPERSET to EMBEDDABLE_CHARTS to match the component's usage of FeatureFlag.EmbeddableCharts, ensuring tests correctly disable the embed code functionality.
    • Feature flag consistency · Line 276-276
      This change updates the feature flag from EMBEDDED_SUPERSET to EMBEDDABLE_CHARTS to match the component's usage of FeatureFlag.EmbeddableCharts, ensuring tests correctly enable the embed code functionality.
    • Feature flag consistency · Line 294-294
      This change updates the feature flag from EMBEDDED_SUPERSET to EMBEDDABLE_CHARTS to match the component's usage of FeatureFlag.EmbeddableCharts, ensuring tests correctly enable the embed code functionality.
    • Feature flag consistency · Line 316-316
      This change updates the feature flag from EMBEDDED_SUPERSET to EMBEDDABLE_CHARTS to match the component's usage of FeatureFlag.EmbeddableCharts, ensuring tests correctly enable the embed code functionality.
Review Details
  • Files reviewed - 33 · Commit Range: 66ad889..e3ff87e
    • superset-frontend/src/dashboard/components/EmbeddedChartModal/index.tsx
    • superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx
    • superset-frontend/src/dashboard/types.ts
    • superset-frontend/src/embeddedChart/index.tsx
    • superset-frontend/src/explore/components/ExploreChartHeader/index.jsx
    • superset-frontend/src/explore/components/useExploreAdditionalActionsMenu/index.jsx
    • superset-frontend/src/pages/EmbeddedChartsList/index.tsx
    • superset-frontend/src/views/routes.tsx
    • superset-frontend/webpack.config.js
    • superset/charts/api.py
    • superset/charts/schemas.py
    • superset/commands/chart/delete.py
    • superset/commands/chart/exceptions.py
    • superset/config.py
    • superset/daos/chart.py
    • superset/embedded_chart/__init__.py
    • superset/embedded_chart/api.py
    • superset/embedded_chart/exceptions.py
    • superset/embedded_chart/view.py
    • superset/initialization/__init__.py
    • superset/mcp_service/app.py
    • superset/mcp_service/embedded_chart/__init__.py
    • superset/mcp_service/embedded_chart/schemas.py
    • superset/mcp_service/embedded_chart/tool/__init__.py
    • superset/mcp_service/embedded_chart/tool/get_embeddable_chart.py
    • superset/migrations/versions/2026-01-08_16-45_50aff65919a0_add_embedded_charts_table.py
    • superset/models/embedded_chart.py
    • superset/models/slice.py
    • superset/security/guest_token.py
    • superset/security/manager.py
    • superset/views/embedded_charts.py
    • tests/integration_tests/charts/api_tests.py
    • tests/integration_tests/security_tests.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

- Add @permission_name("set_embedded") decorator to set_embedded endpoint
- Fix error handling in EmbeddedChartModal to always set ready state
- Add datasource validation in embedded chart API create endpoint

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@codeant-ai-for-open-source
Copy link
Contributor

CodeAnt AI is running Incremental review


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@bito-code-review
Copy link
Contributor

bito-code-review bot commented Jan 9, 2026

Code Review Agent Run #86e5b3

Actionable Suggestions - 0
Review Details
  • Files reviewed - 33 · Commit Range: e3ff87e..8128449
    • superset-frontend/src/dashboard/components/EmbeddedChartModal/index.tsx
    • superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx
    • superset-frontend/src/dashboard/types.ts
    • superset-frontend/src/embeddedChart/index.tsx
    • superset-frontend/src/explore/components/ExploreChartHeader/index.jsx
    • superset-frontend/src/explore/components/useExploreAdditionalActionsMenu/index.jsx
    • superset-frontend/src/pages/EmbeddedChartsList/index.tsx
    • superset-frontend/src/views/routes.tsx
    • superset-frontend/webpack.config.js
    • superset/charts/api.py
    • superset/charts/schemas.py
    • superset/commands/chart/delete.py
    • superset/commands/chart/exceptions.py
    • superset/config.py
    • superset/daos/chart.py
    • superset/embedded_chart/__init__.py
    • superset/embedded_chart/api.py
    • superset/embedded_chart/exceptions.py
    • superset/embedded_chart/view.py
    • superset/initialization/__init__.py
    • superset/mcp_service/app.py
    • superset/mcp_service/embedded_chart/__init__.py
    • superset/mcp_service/embedded_chart/schemas.py
    • superset/mcp_service/embedded_chart/tool/__init__.py
    • superset/mcp_service/embedded_chart/tool/get_embeddable_chart.py
    • superset/migrations/versions/2026-01-08_16-45_50aff65919a0_add_embedded_charts_table.py
    • superset/models/embedded_chart.py
    • superset/models/slice.py
    • superset/security/guest_token.py
    • superset/security/manager.py
    • superset/views/embedded_charts.py
    • tests/integration_tests/charts/api_tests.py
    • tests/integration_tests/security_tests.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Related to the REST API change:frontend Requires changing the frontend risk:db-migration PRs that require a DB migration size/XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants