T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/transcribe.py:107
- Finding
- Arbitrary outbound requests through weak short-link validation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/transcribe.py:107-116` **Vulnerability Type**: Server-Side Request Forgery through insufficient URL validation **Risk Level**: Medium ### Vulnerable Code ```python # Short link b23.tv: follow one redirect if "b23.tv" in url: try: req = urllib.request.Request(url, headers={"User-Agent": PC_UA}) with urllib.request.urlopen(req, timeout=10) as resp: final_url = resp.geturl() m = re.search(r'(BV[0-9A-Za-z]{10})', final_url) if m: return m.group(1) except Exception as e: print(f"[WARN] Failed to follow short link: {e}", file=sys.stderr) ``` ### Technical Analysis The condition only checks whether the literal string `b23.tv` occurs anywhere in the user-supplied value. It does not parse the URL or verify that its hostname is actually `b23.tv`. Consequently, inputs such as the following pass the check even though their destination is not Bilibili: ```text http://127.0.0.1:8080/?source=b23.tv http://169.254.169.254/latest/meta-data/?host=b23.tv https://attacker.example/path/b23.tv ``` The complete user-controlled URL is then passed to `urllib.request.urlopen`. The library also follows HTTP redirects by default, and the code validates neither intermediate redirect targets nor the final target before making the requests. This behavior exceeds the documented minimum-privilege network boundary, which states that the Skill accesses Bilibili endpoints and Hugging Face model infrastructure only. ### Attack Path 1. An attacker supplies a URL whose path, query, or user-information component contains `b23.tv`. 2. `extract_bvid` fails to find a directly embedded BVID. 3. The substring condition evaluates to true. 4. The Skill submits a GET request to the attacker-selected destination. 5. The target can redirect the request to another public or internal endpoint. 6. Response timing, errors, and behavioral differences may allow ...[truncated 874 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse the URL with `urllib.parse.urlsplit` or `urllib.parse.urlparse`. 2. Require the `https` scheme. 3. Require an exact normalized hostname match against `b23.tv`, or a narrowly defined and reviewed subdomain allowlist. 4. Reject URLs containing credentials, unexpected ports, malformed hostnames, or ambiguous encodings. 5. Resolve the hostname and reject loopback, private, link-local, multicast, unspecified, and reserved IP addresses using the `ipaddress` module. 6. Disable automatic redirects or use a custom redirect handler that validates every destination before following it. 7. Apply the same validation after DNS resolution and on every redirect to mitigate DNS rebinding. 8. Add tests covering URLs where `b23.tv` appears only in the path, query, fragment, user-information component, or a different hostname. A safe validation pattern should resemble: ```python from urllib.parse import urlsplit parsed = urlsplit(url) if parsed.scheme != "https" or parsed.hostname != "b23.tv": raise ValueError("Only HTTPS b23.tv short links are accepted") ``` This hostname check should be supplemented with resolved-address and redirect validation. ]]>
