T05 · Unauthorized Access and Privilege Escalation
Warning
- Location
- scripts/_fulfillment_api_runner.py:259
- Finding
- Generic fulfillment proxy permits operations beyond the Skill's read-only purpose<![CDATA[ ## Vulnerability Details **File Location**: `scripts/_fulfillment_api_runner.py:259-297`; related validation in `scripts/_shop_fulfillment_common.py:110-149` **Vulnerability Type**: T05: Unauthorized Access and Privilege Escalation **Risk Level**: Medium ### Vulnerable Code ```python def run_fulfillment_proxy(params: dict, caller: str = "fulfillment_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("fulfillment/") 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=(",", ":")) if "requestBody" in params and body is None: rb = params["requestBody"] body = rb if isinstance(rb, str) else json.dumps(rb, ensure_ascii=False, separators=(",", ":")) proxy = developer_proxy_call( open_id, str(path), str(method).upper(), region=params.get("region"), query_string=query_string, body=body, content_type=str(params.get("contentType") or "application/json"), ) ``` The applicable path validation is: ```python def assert_path_allowed(path: str) -> None: normalized = path.lstrip("/").replace("\\", "/") if ".." in normalized or "//" in normali ...[truncated 3436 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove or disable the generic proxy for the current read-only Skill. 2. Enforce an exact allowlist of method and path pairs: - `GET authorization/202309/shops` - `GET fulfillment/202309/orders/split_attributes` 3. Reject all methods other than those explicitly registered for each endpoint. 4. Validate query parameters and bodies against endpoint-specific schemas rather than accepting arbitrary data. 5. Maintain separate read-only and mutation-capable tools if future fulfillment operations are added. 6. Require explicit user confirmation before every state-changing operation. 7. Apply equivalent endpoint and method restrictions at the LinkFox gateway so client-side checks are not the sole security boundary. 8. Use narrowly scoped TikTok application permissions and seller tokens wherever the platform supports them. ]]>
