T05 · Unauthorized Access and Privilege Escalation
Warning
- Location
- scripts/_return_refund_api_runner.py:258
- Finding
- Generic Authenticated Proxy Exceeds the Skill's Declared Read-Only Scope## Vulnerability Details **File Location**: `scripts/_return_refund_api_runner.py:258-297`, with the exposed entry point at `scripts/return_refund_proxy.py:12-22` and broad path validation at `scripts/_shop_return_refund_common.py:106-124` **Vulnerability Type**: Excessive API capability and insufficient authorization boundary enforcement **Risk Level**: Medium ### Vulnerable Code ```python # scripts/return_refund_proxy.py:12-22 def main() -> None: if len(sys.argv) < 2: print( "Usage: return_refund_proxy.py '<JSON>'\n" "Required: openId, path, method\n" "path whitelist: return_refund/, authorization/", file=sys.stderr, ) sys.exit(1) params = json.loads(sys.argv[1]) print(json.dumps(run_return_refund_proxy(params, "return_refund_proxy.py"), indent=2, ensure_ascii=False)) ``` ```python # scripts/_return_refund_api_runner.py:258-297 def run_return_refund_proxy(params: dict, caller: str = "return_refund_proxy.py") -> dict: """Generic proxy: path + method + openId (+ optional shop_cipher).""" if not params.get("skipDepCheck"): ensure_auth_skill_available(caller) path = params.get("path") method = params.get("method") if not path or not method: print("Missing required fields: path, method", file=sys.stderr) sys.exit(1) open_id = require_open_id(params) shop_cipher = None needs_cipher = str(path).lstrip("/").startswith("return_refund/") if needs_cipher: shop_cipher = resolve_shop_cipher(params, open_id) query_string = params.get("queryString") if shop_cipher: pairs = dict(parse_qsl(str(query_string or "").lstrip("?"), keep_blank_values=True)) pairs["shop_cipher"] = shop_cipher query_string = urlencode(pairs) body = params.get("body") if body is not None and not isinstance(body, str): body = json.dumps(body, ensure_ascii=False, separators=(",", ":")) ...[truncated 3868 chars]
- Remediation
- ## Remediation Suggestions 1. Remove `return_refund_proxy.py` from this read-only Skill unless generic forwarding is essential. 2. Replace namespace-prefix validation with an exact method-and-path allowlist: - `GET authorization/202309/shops` - `GET return_refund/202309/reject_reasons` 3. Reject all methods other than `GET` in the current Skill. 4. Route requests exclusively through `RETURN_REFUND_ENDPOINTS` so callers cannot select arbitrary paths or methods. 5. If write operations are added later, implement each as a separate named API with: - Exact path and method validation. - A strict request schema. - Rejection of undocumented body and query fields. - Explicit user confirmation immediately before execution. - Clear disclosure that the operation changes seller data. 6. Enforce the same exact allowlist at the LinkFox gateway so client-side validation is not the sole security boundary. 7. Add automated negative tests confirming that arbitrary paths and `POST`, `PUT`, `PATCH`, and `DELETE` methods are rejected.
