T09 · Insecure Skill Coding Practices
- Location
scripts/downloader.py:102- Finding
Improper TikTok Hostname Validation Allows Non-TikTok URLs
- Content
View full analysis
Vulnerability Details
File Location:
scripts/downloader.py, lines 102–108
Vulnerability Type: Improper hostname validation
Risk Level: MediumVulnerable Code
python def is_tiktok_link(url): """Check if the URL is a TikTok video link (web link or short link). Supports: - https://www.tiktok.com/@user/video/xxxxx - https://vm.tiktok.com/xxxxx/ - https://vt.tiktok.com/xxxxx/ """ try: parsed = urlparse(url) host = (parsed.hostname or "").lower() return host.endswith("tiktok.com") except Exception: return FalseThe accepted URL is subsequently transmitted to the external RedFox service at line 172:
python resp = session.post( API_URL, json={"url": url, "source": "TikTok视频下载-GitHub"}, timeout=30 )Technical Analysis
The hostname allowlist uses
host.endswith("tiktok.com")without enforcing a DNS-label boundary. Consequently, attacker-controlled domains such aseviltiktok.comandnot-tiktok.comsatisfy the check even though they are not TikTok domains.The validation also does not enforce HTTPS, an expected TikTok video path, a permitted port, or the absence of embedded credentials. This is weaker than the documented behavior, which states that non-TikTok links are rejected.
The local script does not directly retrieve the user-supplied URL. Instead, it includes that URL in an authenticated request to RedFox. Therefore, this audit confirms a validation bypass and unintended URL disclosure to the external service, but it does not establish local server-side request forgery. Any downstream request behavior depends on RedFox's implementation.
Attack Path
- An attacker provides a crafted URL whose hostname merely ends with the string
tiktok.com, such ashttps://eviltiktok.com/resource. urlparse()extractseviltiktok.comas the hostname.host.endswith("tiktok.com")evaluates toTrue.- The script treats the URL as an ...[truncated 830 chars]
- An attacker provides a crafted URL whose hostname merely ends with the string
- Remediation
View remediation
Remediation Suggestions
Replace the raw suffix comparison with an exact hostname allowlist and require HTTPS:
python ALLOWED_HOSTS = { "www.tiktok.com", "vm.tiktok.com", "vt.tiktok.com", } def is_tiktok_link(url): try: parsed = urlparse(url) host = (parsed.hostname or "").lower().rstrip(".") if parsed.scheme != "https": return False if host not in ALLOWED_HOSTS: return False if parsed.username is not None or parsed.password is not None: return False if parsed.port not in (None, 443): return False if host == "www.tiktok.com": return bool(re.fullmatch(r"/@[^/]+/video/\d+/?", parsed.path)) return bool(re.fullmatch(r"/[A-Za-z0-9_-]+/?", parsed.path)) except (ValueError, TypeError): return FalseIf all TikTok subdomains must be supported, enforce a DNS-label boundary:
python host == "tiktok.com" or host.endswith(".tiktok.com")Exact hostnames are preferable because the documented feature supports a limited set of hosts. In addition:
- Validate the expected path format for each approved hostname.
- Reject non-HTTPS schemes, embedded credentials, and unexpected ports.
- Normalize trailing dots before hostname comparison.
- Add regression tests covering:
- Valid
www.tiktok.com,vm.tiktok.com, andvt.tiktok.comURLs. eviltiktok.com,not-tiktok.com, andtiktok.com.attacker.example.- HTTP URLs, malformed URLs, embedded credentials, and unexpected ports.
- Valid
- Ensure that RedFox independently validates the supplied URL against the same strict allowlist before performing any server-side retrieval.
