T09 · Insecure Skill Coding Practices
Note
- Location
- scripts/build_url.py:35
- Finding
- Unencoded Category Parameter Allows Query-String Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/build_url.py`, lines 35-39 **Vulnerability Type**: URL query-string injection / parameter pollution **Risk Level**: Low ### Vulnerable Code ```python if args.category: params["categoryId"] = args.category query_string = "&".join(f"{k}={v}" for k, v in params.items()) url = f"https://www.alibaba.com/trade/search?{query_string}" ``` ### Technical Analysis The `--category` argument is controlled by the command-line user and is assigned directly to `params["categoryId"]`. The query string is then constructed through manual string concatenation rather than a URL-encoding function. Because reserved URL characters such as `&`, `=`, and `#` are not encoded, a crafted category value can escape the intended `categoryId` value and introduce additional query parameters or a URL fragment. The search query itself is encoded by `encode_query`, but that protection is not applied to the category value. For example: ```bash python3 scripts/build_url.py search "wireless earbuds" \ --category '44&attackerControlled=value' ``` This produces a URL equivalent to: ```text https://www.alibaba.com/trade/search?SearchText=wireless+earbuds&traffic_type=ags_llm&categoryId=44&attackerControlled=value ``` The injected `attackerControlled` parameter is interpreted independently rather than as part of `categoryId`. ### Attack Path 1. An attacker supplies or persuades a user or automation system to use a crafted category value containing URL delimiters. 2. The value is accepted by the `--category` command-line argument without validation. 3. The script inserts the value directly into the query string. 4. The script prints an apparently legitimate URL on the fixed `www.alibaba.com` host. 5. If that URL is opened or passed to another component, Alibaba or an intermediary processes the injected parameters according to its own parameter-handling rules. This path requires control over the category argument. It does n ...[truncated 615 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Use `urllib.parse.urlencode` to encode every parameter consistently instead of manually joining key-value pairs: ```python params = { "SearchText": args.query, "traffic_type": TRAFFIC_TYPE, } if args.category: params["categoryId"] = args.category query_string = urllib.parse.urlencode(params) url = f"https://www.alibaba.com/trade/search?{query_string}" ``` Because `urlencode` performs value encoding, pass the raw search query rather than the output of `encode_query`; otherwise, percent characters may be encoded twice. If category identifiers are expected to be numeric, add allowlist validation as defense in depth: ```python if args.category: if not args.category.isdigit(): parser.error("--category must contain digits only") params["categoryId"] = args.category ``` Add regression tests using values containing `&`, `=`, `#`, `%`, whitespace, and Unicode. Verify that these characters are encoded within `categoryId` and cannot create separate query parameters. ]]>
