T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/geekbi_auth.py:698
- Finding
- Unrestricted API Origin Can Receive Authentication Material<![CDATA[ ## Vulnerability Details **File Location**: `scripts/coupang_goods_search.py:65-72`, `scripts/coupang_search_common.py:108-111`, and `scripts/geekbi_auth.py:564-578, 698-721` **Vulnerability Type**: Missing destination and transport validation for authenticated requests **Risk Level**: Medium ### Vulnerable Code ```python # scripts/coupang_goods_search.py:65-72 parser.add_argument("--base-url", default=DEFAULT_BASE_URL) parser.add_argument("--param", action="append", default=[], help="查询条件,格式为 名称=值") parser.add_argument("--timeout", type=float, default=30) args = parser.parse_args() try: params = parse_params(args.param) payload = authenticated_json_request( build_url(args.base_url, ENDPOINT, params), args.base_url, args.timeout ) ``` ```python # scripts/coupang_search_common.py:108-111 def build_url(base_url, endpoint, params): url = f"{base_url.rstrip('/')}{endpoint}" query = urlencode(params) return f"{url}?{query}" if query else url ``` ```python # scripts/geekbi_auth.py:564-578 def complete_pending_login(base_url, timeout): payload = _load_state() server_key = _server_key(base_url) server = payload["servers"].get(server_key) if not isinstance(server, dict): return False now = int(time.time()) changed = _clear_expired(server, now) pending = server.get("pending") if not isinstance(pending, dict): if changed: _persist_expiry_cleanup(server_key, now) return False endpoint = f"{base_url.rstrip('/')}{TOKEN_ENDPOINT}" ``` ```python # scripts/geekbi_auth.py:698-721 def authenticated_json_request( url, base_url, timeout, *, method="GET", body=None, headers=None, ): complete_pending_login(base_url, timeout) request_headers = _api_headers() if headers: request_headers.update(headers) authorization = _authorization_header(base_url) if authorization: request_headers["token"] = authorizatio ...[truncated 3148 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `--base-url` from production-facing commands if endpoint customization is not required. 2. Otherwise, parse the URL with `urllib.parse.urlsplit()` and require: - The `https` scheme. - An exact approved hostname such as `openapi.geekbi.com`. - An approved port. - No embedded username or password. - No fragments or malformed authority components. 3. Before attaching a bearer value, independently verify that `url` and `base_url` resolve to the same approved origin. 4. Reject redirects to different origins for authenticated requests, or implement explicit same-origin redirect validation. 5. Validate server-provided login links against a separate allowlist of HTTPS authentication hosts before displaying them. 6. If custom development endpoints are necessary, gate them behind an explicit unsafe-development option and use isolated test credentials that cannot access production data. 7. Add tests proving that HTTP URLs, deceptive hostnames, embedded credentials, nonstandard ports, and unapproved origins are rejected. ]]>
