Skip to content

Vanna query should be validated before executed #1817

@sytranvn

Description

@sytranvn

Is this a new feature, an improvement, or a change to existing functionality?

Change

How would you describe the priority of this feature request

Medium

Please provide a clear description of problem this feature solves

Feature Request: text2sql should not execute Destructive SQL Operations

Description

Currently, the Vanna plugin text2sql function appears to execute generated SQL queries directly (when execute_sql=true). While this is efficient for SELECT statements, it poses a significant risk when the model generates queries that modify, delete, or structure data (e.g., INSERT, UPDATE, DELETE, DROP, ALTER).

To improve security and prevent accidental data loss, I propose hardening the execution rules so that any non-read-only query is returned to the user as text for manual review and execution, rather than being run automatically.

Suggested Behavior

  1. Generate any SQL statement
  2. use vanna_instance.is_sql_valid(sql=... check if the SQL should be run.
    Conditional Execution:
    • Read-only (SELECT): Continue to execute and display results as usual.
    • Destructive/Modifying: Instead of executing, the plugin display the SQL with explanation to the user.
  3. User Confirmation: User review the SQL and run it manually in her database terminal if it looks correct.

Use Case / Rationale

  • Safety: Prevents the LLM from accidentally hallucinating a WHERE clause incorrectly on a DELETE or UPDATE statement.
  • Security: Reduces the risk of "Prompt Injection" resulting in unauthorized data modification.

Describe your ideal solution

  @register_function(config_type=Text2SQLConfig, framework_wrappers=[LLMFrameworkEnum.LANGCHAIN])
  async def text2sql(config: Text2SQLConfig, builder: Builder):
      """Register the Text2SQL function with Vanna integration."""
      # ...
            sql = str(sql_result.get("sql", ""))
            explanation: str | None = sql_result.get("explanation")
            is_valid_sql = vanna_instance.is_sql_valid(sql)  # <------ add this check

            # If execute_sql is enabled, run the query
            if config.execute_sql and is_valid_sql:
                yield ResponseIntermediateStep(
                    id=str(uuid.uuid4()),
                    parent_id=parent_id,
                    type="markdown",
                    name="text2sql_status",
                    payload=StatusPayload(message="Executing SQL query...").model_dump_json(),
                )
                # Execute SQL and propagate errors
                # Note: run_sql is dynamically set as async function in setup_vanna_db_connection
                df = await vanna_instance.run_sql(sql)  # type: ignore[misc]
                logger.info(f"SQL executed successfully: {len(df)} rows returned")

            # Yield final result as Text2SQLOutput
            yield Text2SQLOutput(sql=sql, explanation=explanation)

Additional context

https://try.vanna.ai/docs/hardening-guide/

Code of Conduct

  • I agree to follow this project's Code of Conduct
  • I have searched the open feature requests and have found no duplicates for this feature request

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs TriageNeed team to review and classifyfeature requestNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions