codeant-ai-for-open-source[bot] commented on code in PR #42412:
URL: https://github.com/apache/superset/pull/42412#discussion_r3654134542


##########
superset/commands/streaming_export/base.py:
##########
@@ -219,19 +218,39 @@ def _execute_query_and_stream(
         delimiter = csv_export_config.get("sep", ",")
         decimal_separator = csv_export_config.get("decimal", ".")
 
+        # Apply SQL mutations (e.g. SQL_QUERY_MUTATOR config hook) before
+        # execution.  All non-streaming paths go through this — the streaming
+        # path was originally skipping it, which left trailing semicolons
+        # unstripped for engines like Trino that reject them.
+        sql = database.mutate_sql_based_on_config(sql)
+
         with db.session(future=True) as session:
             # Merge database to prevent DetachedInstanceError
             merged_database = session.merge(database)
 
-            with merged_database.get_sqla_engine(
-                catalog=catalog, schema=schema
-            ) as engine:
-                with engine.connect() as connection:
-                    result_proxy = connection.execution_options(
-                        stream_results=True
-                    ).execute(text(sql))
-
-                    columns = list(result_proxy.keys())
+            # Use get_raw_connection() instead of get_sqla_engine() directly.
+            # This is critical for:
+            # 1. User impersonation — get_raw_connection() goes through the
+            #    ENGINE_CONTEXT_MANAGER which applies impersonate_user settings
+            #    (e.g. X-Trino-User header).  Without this, all streaming CSV
+            #    exports run as the service principal, breaking audit trails
+            #    and potentially bypassing per-user authorization (Ranger, OPA,
+            #    RLS views).
+            # 2. SSH tunnels — get_raw_connection() sets up SSH tunnels if
+            #    configured on the database.
+            # 3. OAuth2 — get_raw_connection() wraps execution in
+            #    check_for_oauth2() context.
+            with closing(
+                merged_database.get_raw_connection(catalog=catalog, 
schema=schema)
+            ) as conn:

Review Comment:
   **Suggestion:** `get_raw_connection()` is used with `closing()`, which only 
calls `close()` and does not enter or exit a context manager. Since this API 
provides the connection through a context manager to apply lifecycle handling 
such as OAuth2 cleanup, SSH tunnel management, and impersonation context, 
`conn` becomes the context-manager object rather than the raw DBAPI connection; 
`conn.cursor()` therefore fails or bypasses the required setup. Use the 
connection as a context manager directly and keep cursor cleanup inside that 
context. [resource leak]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Streaming CSV exports fail before query execution.
   - ❌ User impersonation and OAuth2 setup are bypassed.
   - ❌ SSH tunnel lifecycle handling is not entered or exited.
   - ⚠️ Export consumers receive stream errors instead of CSV output.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Start a streaming CSV export through the streaming export command; 
`run()` at
   `superset/commands/streaming_export/base.py:295` returns a generator whose 
consumption
   executes `_execute_query_and_stream()`.
   
   2. Consume the returned generator so execution reaches
   `superset/commands/streaming_export/base.py:243-245`, where
   `merged_database.get_raw_connection(catalog=catalog, schema=schema)` is 
wrapped with
   `contextlib.closing` instead of being entered with a `with` statement.
   
   3. `get_raw_connection()` provides a context-managed connection so its 
`__enter__` logic
   establishes the raw connection and its impersonation, OAuth2, and SSH-tunnel 
contexts;
   `closing` does not invoke that context manager's `__enter__`.
   
   4. The assigned `conn` is therefore the context-manager wrapper rather than 
the DBAPI
   connection, and `conn.cursor()` at 
`superset/commands/streaming_export/base.py:246` fails
   before `cursor.execute(sql)` at line 248. The export generator emits a 
stream failure
   instead of CSV data; cleanup is also not performed through the connection 
context.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=4dd8f94a555b43559cfc8a7982473a91&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=4dd8f94a555b43559cfc8a7982473a91&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/commands/streaming_export/base.py
   **Line:** 243:245
   **Comment:**
        *Resource Leak: `get_raw_connection()` is used with `closing()`, which 
only calls `close()` and does not enter or exit a context manager. Since this 
API provides the connection through a context manager to apply lifecycle 
handling such as OAuth2 cleanup, SSH tunnel management, and impersonation 
context, `conn` becomes the context-manager object rather than the raw DBAPI 
connection; `conn.cursor()` therefore fails or bypasses the required setup. Use 
the connection as a context manager directly and keep cursor cleanup inside 
that context.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42412&comment_hash=3ce53f2385557ea58253fa631c35e548a0076122d808427138733aa47aea0324&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42412&comment_hash=3ce53f2385557ea58253fa631c35e548a0076122d808427138733aa47aea0324&reaction=dislike'>👎</a>



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to