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


##########
superset/dashboards/api.py:
##########
@@ -1058,11 +1058,15 @@ def put_colors(self, pk: int) -> Response:
             return self.response_400(message=error.messages)
 
         try:
+            dry_run = parse_boolean_string(request.args.get("dry_run", 
"false"))
             mark_updated = parse_boolean_string(
                 request.args.get("mark_updated", "true")
             )
-            UpdateDashboardColorsConfigCommand(pk, item, mark_updated).run()
-            response = self.response(200)
+            if dry_run:
+                response = self.response(200)
+            else:
+                UpdateDashboardColorsConfigCommand(pk, item, 
mark_updated).run()
+                response = self.response(200)

Review Comment:
   **Suggestion:** The `dry_run` branch skips 
`UpdateDashboardColorsConfigCommand.run()`, which is where dashboard existence 
and ownership checks happen. That causes `dry_run=true` requests to return 200 
even for non-existent dashboards or dashboards the caller is not allowed to 
modify. Keep the same validation/authorization path for dry runs (for example, 
add a dry-run mode to the command that runs validation but skips persistence). 
[security]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Dry-run colors endpoint returns 200 for nonexistent dashboard IDs.
   - ❌ Dry-run bypasses DashboardDAO existence and raise_for_ownership 
validations.
   - ⚠️ Clients may accept invalid dashboard colors config as valid.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Start Superset with this PR code and note the dashboard colors update 
endpoint
   `put_colors` defined in `superset/dashboards/api.py` at lines 10-85 of the 
snippet
   returned by Read (header "Showing lines 1000 to 1199"), exposed via
   `@expose("/<pk>/colors", methods=("PUT",))` inside `DashboardRestApi`.
   
   2. Send an HTTP `PUT` request to 
`/api/v1/dashboard/<pk>/colors?dry_run=true` with a valid
   JSON body (so Marshmallow validation in `put_colors` at `api.py` lines 56-59 
passes), but
   choose `<pk>` to be a dashboard ID that does not exist in the database (or 
one the current
   user does not own).
   
   3. The request enters `DashboardRestApi.put_colors` (`api.py` lines 56-85); 
inside the
   second `try:` block at lines 61-70, `dry_run` is parsed as `True`, so the 
branch at lines
   66-70 executes: `if dry_run: response = self.response(200)` and the method 
returns without
   ever invoking `UpdateDashboardColorsConfigCommand(pk, item, 
mark_updated).run()`.
   
   4. Because `UpdateDashboardColorsConfigCommand.run()`
   (`superset/commands/dashboard/update.py` lines 40-63) calls 
`super().validate()` which in
   turn runs `UpdateDashboardCommand.validate` (`update.py` lines 42-88) to (a) 
look up the
   dashboard via `DashboardDAO.find_by_id(self._model_id)` and raise
   `DashboardNotFoundError()` if missing, and (b) enforce ownership via
   `security_manager.raise_for_ownership(self._model)` raising 
`DashboardForbiddenError()` on
   failure, skipping `run()` in the dry-run branch means none of these checks 
execute, no
   exception is raised, and the client receives HTTP 200 instead of the 
expected 404/403 for
   nonexistent or unauthorized dashboards.
   ```
   </details>
   
   [Fix in 
Cursor](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=9ec964742a52469090a45215c4578745&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 | [Fix in VSCode 
Claude](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=9ec964742a52469090a45215c4578745&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/dashboards/api.py
   **Line:** 1065:1069
   **Comment:**
        *Security: The `dry_run` branch skips 
`UpdateDashboardColorsConfigCommand.run()`, which is where dashboard existence 
and ownership checks happen. That causes `dry_run=true` requests to return 200 
even for non-existent dashboards or dashboards the caller is not allowed to 
modify. Keep the same validation/authorization path for dry runs (for example, 
add a dry-run mode to the command that runs validation but skips persistence).
   
   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%2F40282&comment_hash=77a3af389bc28dd4a77b36e3e571d065c0844ce81cf4efd2ee195e905d784255&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40282&comment_hash=77a3af389bc28dd4a77b36e3e571d065c0844ce81cf4efd2ee195e905d784255&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