alexandrusoare commented on code in PR #43111:
URL: https://github.com/apache/superset/pull/43111#discussion_r3803339131


##########
superset/security/manager.py:
##########
@@ -1107,6 +1107,130 @@ def _orderby_modified(
     return False
 
 
+def _collect_allowed_sql_extras(
+    stored_chart: "Slice",
+    stored_query_context: Optional[dict[str, Any]],
+) -> tuple[set[str], set[str]]:
+    """
+    Collect the ``extras.where`` and ``extras.having`` values that a guest user
+    is allowed to send, derived from the stored chart and its query context.
+    """
+    from superset.common.form_data_query_context import freeform_where_having
+
+    allowed_where: set[str] = set()
+    allowed_having: set[str] = set()
+
+    stored_extras = freeform_where_having(stored_chart.params_dict)
+    if stored_extras.get("where"):
+        allowed_where.add(stored_extras["where"])
+    if stored_extras.get("having"):
+        allowed_having.add(stored_extras["having"])
+
+    if stored_query_context:
+        for query in stored_query_context.get("queries") or []:
+            extras = query.get("extras") or {}
+            if extras.get("where"):
+                allowed_where.add(extras["where"])
+            if extras.get("having"):
+                allowed_having.add(extras["having"])
+
+    return allowed_where, allowed_having
+
+
+# The frontend emits ``{expressionType: "SQL", sqlExpression: "1 = 0"}`` when
+# a native Select filter has "Filter value is required" enabled and no value
+# has been selected yet (superset-frontend/src/filters/utils.ts).  After
+# ``_sanitize_clause`` wraps it in parentheses the resulting ``extras.where``
+# value is ``(1 = 0)``.  This is safe — it returns zero rows — and must be
+# allowed so that embedded charts are not rejected before the user picks a
+# filter value.
+_EMPTY_FILTER_SENTINEL = "(1 = 0)"
+
+
+def _filter_has_adhoc_sql_col(flt: Any) -> bool:
+    """
+    Whether a structured ``{col, op, val}`` filter carries an adhoc column
+    with a ``sqlExpression``, which would reach ``adhoc_column_to_sqla``
+    and execute arbitrary SQL in the WHERE clause.
+    """
+    if not isinstance(flt, dict):
+        return False
+    col = flt.get("col")
+    return (
+        isinstance(col, dict)
+        and isinstance(col.get("sqlExpression"), str)
+        and bool(col.get("sqlExpression"))
+    )
+
+
+def _query_extras_sql_modified(
+    query: Any,
+    allowed_where: set[str],
+    allowed_having: set[str],
+) -> bool:
+    """
+    Whether a single query's ``extras.where``/``extras.having`` or structured
+    filters inject SQL not present on the stored chart.
+    """
+    extras = query.extras or {}
+    req_where = extras.get("where", "")
+    if req_where and req_where != _EMPTY_FILTER_SENTINEL:
+        if req_where not in allowed_where:
+            return True
+    req_having = extras.get("having", "")
+    if req_having and req_having != _EMPTY_FILTER_SENTINEL:
+        if req_having not in allowed_having:
+            return True
+    for flt in query.filter or []:

Review Comment:
   Addressed



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