codeant-ai-for-open-source[bot] commented on code in PR #40823:
URL: https://github.com/apache/superset/pull/40823#discussion_r3366614914
##########
superset/extensions/api.py:
##########
@@ -102,18 +146,68 @@ def get_list(self, **kwargs: Any) -> Response:
500:
$ref: '#/components/responses/500'
"""
- result = []
extensions = get_extensions()
- for extension in extensions.values():
- extension_data = build_extension_data(extension)
- result.append(extension_data)
+ ext_list = list(extensions.values())
+
+ q_args: dict[str, Any] = {}
+ if q_str := request.args.get("q"):
+ try:
+ q_args = rison.loads(q_str)
+ except Exception:
+ return self.response_400(message="Invalid rison query
parameter")
+
+ if not isinstance(q_args, dict):
+ return self.response_400(
+ message="Query parameter must be a rison object"
+ )
+
+ ext_list, error = self._apply_q(ext_list, q_args)
+ if error:
+ return self.response_400(message=error)
+
+ total_count = len(ext_list)
+
+ page = q_args.get("page")
+ page_size = q_args.get("page_size", DEFAULT_PAGE_SIZE)
+ if page is not None:
+ start = page * page_size
+ ext_list = ext_list[start : start + page_size]
+
+ result = [build_extension_data(ext) for ext in ext_list]
+ return self.response(200, result=result, count=total_count)
+
+ @staticmethod
+ def _apply_q(
+ ext_list: list[LoadedExtension], q_args: dict[str, Any]
+ ) -> tuple[list[LoadedExtension], str | None]:
+ """Apply filters and search from a parsed q parameter."""
+ if filters := q_args.get("filters"):
+ if not isinstance(filters, list):
+ return ext_list, "'filters' must be a list"
+ for f in filters:
+ col = f.get("col")
+ value = f.get("value")
Review Comment:
**Suggestion:** The filter loop assumes every entry in `filters` is a dict
and immediately calls `.get(...)`; a malformed payload like `filters=[1]` will
raise `AttributeError` and return 500 instead of a client error. Validate each
filter item is a dict before accessing keys and return a 400 for invalid
shapes. [type error]
<details>
<summary><b>Severity Level:</b> Major ⚠️</summary>
```mdx
- ❌ Extensions listing endpoint 500s on malformed `filters` payload.
- ⚠️ Bad clients can crash endpoint instead of 400 response.
```
</details>
<details>
<summary><b>Steps of Reproduction ✅ </b></summary>
```mdx
1. Start a Superset instance running the PR code so that the
`ExtensionsRestApi` class in
`superset/extensions/api.py:57` is registered by Flask-AppBuilder.
2. Issue an HTTP GET request to the list endpoint handled by
`ExtensionsRestApi.get_list`
(`superset/extensions/api.py:96-177`), with a `q` query parameter containing
a Rison
object where `filters` is a list containing a non-dict element, e.g.
`q=(filters:!(1))`.
3. In `get_list`, the code at `superset/extensions/api.py:152-156` calls
`rison.loads(q_str)` which successfully parses the Rison string into `q_args
= {"filters":
[1]}`, then calls `self._apply_q(ext_list, q_args)` at line 164.
4. Inside `_apply_q` (`superset/extensions/api.py:179-210`), `filters` is a
list so it
passes the `isinstance(filters, list)` check at line 185, then the loop `for
f in
filters:` at line 187 iterates with `f == 1` and immediately executes
`f.get("col")` at
line 188, raising `AttributeError: 'int' object has no attribute 'get'` and
causing a 500
Internal Server Error instead of returning a 400 client error.
```
</details>
[Fix in
Cursor](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=3988f4c58ab94d67a4a129630662e241&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=3988f4c58ab94d67a4a129630662e241&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/extensions/api.py
**Line:** 187:189
**Comment:**
*Type Error: The filter loop assumes every entry in `filters` is a dict
and immediately calls `.get(...)`; a malformed payload like `filters=[1]` will
raise `AttributeError` and return 500 instead of a client error. Validate each
filter item is a dict before accessing keys and return a 400 for invalid shapes.
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%2F40823&comment_hash=3e2dff0af42b1df34c907eac8696d357b641a1cc246083859d7e90af4f9652d0&reaction=like'>👍</a>
| <a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40823&comment_hash=3e2dff0af42b1df34c907eac8696d357b641a1cc246083859d7e90af4f9652d0&reaction=dislike'>👎</a>
##########
superset/extensions/api.py:
##########
@@ -102,18 +146,68 @@ def get_list(self, **kwargs: Any) -> Response:
500:
$ref: '#/components/responses/500'
"""
- result = []
extensions = get_extensions()
- for extension in extensions.values():
- extension_data = build_extension_data(extension)
- result.append(extension_data)
+ ext_list = list(extensions.values())
+
+ q_args: dict[str, Any] = {}
+ if q_str := request.args.get("q"):
+ try:
+ q_args = rison.loads(q_str)
+ except Exception:
+ return self.response_400(message="Invalid rison query
parameter")
+
+ if not isinstance(q_args, dict):
+ return self.response_400(
+ message="Query parameter must be a rison object"
+ )
+
+ ext_list, error = self._apply_q(ext_list, q_args)
+ if error:
+ return self.response_400(message=error)
+
+ total_count = len(ext_list)
+
+ page = q_args.get("page")
+ page_size = q_args.get("page_size", DEFAULT_PAGE_SIZE)
+ if page is not None:
+ start = page * page_size
+ ext_list = ext_list[start : start + page_size]
Review Comment:
**Suggestion:** Pagination parameters from `q` are used without type
validation, so non-integer values (for example `page: "1"` or `page_size:
"10"`) will make `start` and slicing fail with `TypeError`, producing a 500
response. Enforce integer pagination values and reject invalid types with 400.
[type error]
<details>
<summary><b>Severity Level:</b> Major ⚠️</summary>
```mdx
- ❌ Extensions listing endpoint 500s when `page` not integer.
- ⚠️ Pagination misbehaviour prevents clients gracefully handling invalid
inputs.
```
</details>
<details>
<summary><b>Steps of Reproduction ✅ </b></summary>
```mdx
1. Run Superset with the PR code so that `ExtensionsRestApi.get_list` in
`superset/extensions/api.py:96-177` is exposed through Flask-AppBuilder.
2. Send an HTTP GET request to the list endpoint handled by `get_list`,
providing a `q`
query parameter where `page` (or `page_size`) is a non-integer Rison value,
e.g.
`q=(page:'1')` which `rison.loads` parses as `{"page": "1"}`.
3. In `get_list`, after `_apply_q` returns, the code at
`superset/extensions/api.py:170-171` assigns `page = "1"` and `page_size =
100` (default),
then computes `start = page * page_size` at line 173, which yields the
string `"1"`
repeated 100 times because `"1" * 100` is valid Python.
4. The next line `ext_list = ext_list[start : start + page_size]` at
`superset/extensions/api.py:174` attempts to evaluate `start + page_size`
where `start` is
a long string and `page_size` is an `int`, raising `TypeError` and resulting
in a 500
Internal Server Error instead of a 400 response indicating invalid
pagination parameters.
```
</details>
[Fix in
Cursor](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=fe044a2077474fddb9418861711fc2fd&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=fe044a2077474fddb9418861711fc2fd&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/extensions/api.py
**Line:** 170:174
**Comment:**
*Type Error: Pagination parameters from `q` are used without type
validation, so non-integer values (for example `page: "1"` or `page_size:
"10"`) will make `start` and slicing fail with `TypeError`, producing a 500
response. Enforce integer pagination values and reject invalid types with 400.
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%2F40823&comment_hash=e87a9f9f6d7630b9462d1bfb93e67d2b8ba97a147726464be06ccf7e40031a62&reaction=like'>👍</a>
| <a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40823&comment_hash=e87a9f9f6d7630b9462d1bfb93e67d2b8ba97a147726464be06ccf7e40031a62&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]