Skip to content

MCP SQL execution falsely flags identifiers containing disallowed function names #42071

Description

@luoianun

Bug description

When using Superset MCP / Database.execute() with a MySQL-compatible database, the SQL security check for DISALLOWED_SQL_FUNCTIONS appears to match disallowed function names by substring against the full SQL statement.

As a result, normal identifiers that contain words such as user or schema are falsely rejected, even when they are not function calls.

Example sanitized query:

SELECT
  event_date,
  SUM(metric_user_count) AS total_users
FROM some_metrics_table
WHERE event_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)
GROUP BY event_date
LIMIT 5;

Actual result:

Disallowed SQL functions: user

Another generic example is querying MySQL metadata:

SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'example_schema'
LIMIT 3;

This can be falsely rejected as:

Disallowed SQL functions: schema

Expected behavior:

Superset should only reject real SQL function calls such as:

SELECT USER();
SELECT SCHEMA();

It should not reject column names, table names, schema names, or aliases that merely contain those substrings.

Root cause

In superset/sql/execution/executor.py, _check_disallowed_functions() appears to check each disallowed function with substring matching against the statement string:

statement_str = str(statement).upper()
for func in engine_disallowed:
    if func.upper() in statement_str:
        found.add(func)

This causes false positives for identifiers such as:

metric_user_count
information_schema
table_schema

Superset already has AST-based function detection in the SQL parsing layer, for example script.check_functions_present(...), which checks actual function nodes instead of arbitrary substrings.

Suggested fix

Use AST-based function detection instead of substring matching. For example:

found = {
    func
    for func in engine_disallowed
    if script.check_functions_present({func})
}

This keeps the intended protection for real disallowed function calls, while avoiding false positives on identifiers.

Environment

Superset version: 6.1.0
Python version: 3.10
Node version: Not applicable
Browser: Not applicable
Database engine: MySQL-compatible database
Component: Superset MCP SQL execution / Database.execute()

Additional context

This was observed while using Superset MCP to execute read-only SQL and create virtual datasets/charts from a MySQL-compatible database.

A local patch using script.check_functions_present({func}) fixed the false positives:

  • Queries with identifiers containing user succeeded.
  • Queries with information_schema / table_schema succeeded.
  • A real USER() function call was still rejected with Disallowed SQL functions: user.

So the issue seems isolated to function detection using substring matching instead of AST function-call detection.

Checklist

  • I have searched Superset docs and Slack and didn't find a solution to my problem.
  • I have searched the GitHub issue tracker and didn't find a similar bug report.
  • I have checked Superset's logs for errors and if I found a relevant Python stacktrace, I included it here as text in the "additional context" section.

Metadata

Metadata

Assignees

No one assigned

    Labels

    sqllabNamespace | Anything related to the SQL Labvalidation:requiredA committer should validate the issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions