geido commented on code in PR #45273:
URL: https://github.com/apache/superset/pull/45273#discussion_r4288445592


##########
superset/charts/data/api.py:
##########
@@ -563,18 +564,11 @@ def _process_data(query_data: Any) -> Any:
                 # their guest token has been granted "can view query on 
Dashboard",
                 # mirroring the permission the frontend uses to expose the
                 # "View query" action. Stacktraces and driver errors stay 
redacted
-                # regardless, as those leak details of the deployment itself.
-                can_view_query = security_manager.can_access(
-                    "can_view_query", "Dashboard"
-                )
-                for query in queries:
-                    if not can_view_query:
-                        query.pop("query", None)
-                    query.pop("stacktrace", None)
-                    if query.get("error"):
-                        query["error"] = sanitize_error_message(
-                            query["error"], required=sanitize_required
-                        )
+                # regardless, as those leak details of the deployment itself. 
The
+                # same helper redacts the ``/datasource/samples`` (Drill to
+                # detail) response so the two guest-facing endpoints cannot
+                # diverge.
+                redact_sensitive_query_fields(queries, 
required=sanitize_required)

Review Comment:
   Follow-up: once the guard was gone, nothing passed `required` into the 
helper, so Codecov flagged `if required is None` as an unreachable branch. 
c5bab97 dropped the parameter; the helper now [resolves the decision 
itself](https://github.com/apache/superset/blob/3f5800786a70d041958c1e0fea10ad6b8fee92d4/superset/utils/error_sanitization.py#L194)
 and [passes 
`required=True`](https://github.com/apache/superset/blob/3f5800786a70d041958c1e0fea10ad6b8fee92d4/superset/utils/error_sanitization.py#L206)
 into the error sanitization, so the [call 
site](https://github.com/apache/superset/blob/3f5800786a70d041958c1e0fea10ad6b8fee92d4/superset/charts/data/api.py#L560)
 stays a bare call. Behavior is unchanged: the existing chart-data tests pass 
as-is, including 
[`test_send_chart_response_does_not_half_redact_guest_query_error`](https://github.com/apache/superset/blob/3f5800786a70d041958c1e0fea10ad6b8fee92d4/tests/unit_tests/charts/test_chart_data_api.py#L665)
 (still a single `is_guest_user` look
 up) and 
[`test_send_chart_response_keeps_guest_query_when_permitted`](https://github.com/apache/superset/blob/3f5800786a70d041958c1e0fea10ad6b8fee92d4/tests/unit_tests/charts/test_chart_data_api.py#L571).
   



##########
tests/unit_tests/views/datasource/views_test.py:
##########
@@ -888,6 +888,36 @@ def test_samples_proceeds_for_supported_datasource_type(
     view.json_response.assert_called_once_with({"result": {"rows": []}})
 
 
+@patch("superset.views.datasource.views.redact_sensitive_query_fields")

Review Comment:
   One more tightening since (a82a73d): the real-helper test now [captures what 
`json_response` 
serializes](https://github.com/apache/superset/blob/3f5800786a70d041958c1e0fea10ad6b8fee92d4/tests/unit_tests/views/datasource/views_test.py#L939)
 and asserts on that, instead of on the `rv` dict the helper mutates. Checked 
in a scratch copy with the redaction moved after `json_response`: the previous 
assertion still passed, the new one fails.
   



##########
superset/views/datasource/views.py:
##########
@@ -444,6 +445,12 @@ def samples(self) -> FlaskResponse:
             datasource=dataset,
             dashboard_id=dashboard_id,
         )
+        # Drill to detail is available to embedded guests (see the guest branch
+        # above), and the samples payload carries the generated SQL under
+        # ``query``. Apply the same guest redaction ``/api/v1/chart/data`` has
+        # applied since CVE-2025-55673 so the SQL is not disclosed to a guest
+        # whose role lacks "can view query on Dashboard".
+        redact_sensitive_query_fields([rv])

Review Comment:
   Adding the specifics: every failure exit in `get_samples` raises 
`DatasetSamplesFailedError` instead of returning the payload 
([count](https://github.com/apache/superset/blob/3f5800786a70d041958c1e0fea10ad6b8fee92d4/superset/views/datasource/utils.py#L185),
 
[samples](https://github.com/apache/superset/blob/3f5800786a70d041958c1e0fea10ad6b8fee92d4/superset/views/datasource/utils.py#L216)),
 so a failed payload's `query`/`stacktrace` are never serialized. The view sits 
under 
[`@handle_api_exception`](https://github.com/apache/superset/blob/3f5800786a70d041958c1e0fea10ad6b8fee92d4/superset/views/datasource/views.py#L387),
 whose [`SupersetException` 
branch](https://github.com/apache/superset/blob/3f5800786a70d041958c1e0fea10ad6b8fee92d4/superset/views/error_handling.py#L154)
 goes through `json_error_response`, which [swaps the message for 
guests](https://github.com/apache/superset/blob/3f5800786a70d041958c1e0fea10ad6b8fee92d4/superset/views/error_handling.py#L92).
 That's the part that 
 matters, since a SQLAlchemy driver error can quote the full statement as 
`[SQL: ...]`. 
[`test_samples_failure_returns_generic_error_to_guests`](https://github.com/apache/superset/blob/3f5800786a70d041958c1e0fea10ad6b8fee92d4/tests/unit_tests/views/datasource/views_test.py#L1001)
 feeds it such an error and gets a 422 with only the generic message, and an 
end-to-end run with a real guest token and a failing samples query returned the 
same `{"error": "An error occurred while fetching the data."}`. Those tests pin 
existing behavior rather than change it; the guest failure path was already 
safe.
   



-- 
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