T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/ozon_mall_search.py:70
- Finding
- Unrestricted API Base URL Enables Phishing and Insecure Transmission<![CDATA[ ## Vulnerability Details **File Location**: - `scripts/ozon_mall_search.py:70-78` - `scripts/ozon_mall_info.py:35-43` - `scripts/ozon_site_list.py:47-53` - `scripts/ozon_search_common.py:104-107` - `scripts/geekbi_auth.py:578-580, 695-713` **Vulnerability Type**: User-controlled network destination without scheme or hostname validation **Risk Level**: Medium ### Vulnerable Code ```python # scripts/ozon_mall_search.py:70-78 parser.add_argument("--base-url", default=DEFAULT_BASE_URL) parser.add_argument("--param", action="append", default=[], help="查询条件,格式为 名称=值") parser.add_argument("--timeout", type=float, default=45) 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/ozon_mall_info.py:35-43 parser.add_argument("--mall-id", required=True) parser.add_argument("--site-id", type=int, default=1) parser.add_argument("--base-url", default=DEFAULT_BASE_URL) parser.add_argument("--timeout", type=float, default=45) args = parser.parse_args() try: params = build_params(args.mall_id, args.site_id) payload = authenticated_json_request( build_url(args.base_url, ENDPOINT, params), args.base_url, args.timeout ) ``` ```python # scripts/ozon_site_list.py:47-53 parser.add_argument("--country", help="国家、站点 UID 或域名;不传则返回全部") parser.add_argument("--base-url", default=DEFAULT_BASE_URL) parser.add_argument("--timeout", type=float, default=30) args = parser.parse_args() try: payload = authenticated_json_request( f"{args.base_url.rstrip('/')}{ENDPOINT}", args.base_url, args.timeout ) ``` ```python # scripts/ozon_search_common.py:104-107 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:578-580 endpoint = f"{base_url.r ...[truncated 3238 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `--base-url` from production-facing commands and use the fixed `https://openapi.geekbi.com` endpoint. 2. If custom endpoints are required for development, place them behind an explicit development-only option that is disabled by default. 3. Parse endpoints with `urllib.parse.urlsplit` and enforce: - scheme exactly equal to `https`; - hostname exactly matching an approved allowlist; - no username or password component; - only approved ports; - no fragments or ambiguous URL forms. 4. Independently validate every returned `jumpUrl` against an authentication-domain allowlist before storing or displaying it. 5. Reject redirects to unapproved origins. If redirects are required, verify the origin after every redirect. 6. Bind stored authentication state to a canonical, validated origin rather than an arbitrary input string. 7. Add tests covering HTTP URLs, lookalike domains, user-info URLs, alternate ports, malformed URLs, and malicious challenge links. ]]>
