T09 · Insecure Skill Coding Practices
- Location
scripts/kol_creator_discovery.py:86- Finding
Lookalike Domains Accepted by Weak Social Platform Hostname Validation
- Content
View full analysis
str | None: host = urllib.parse.urlsplit(url).netloc.lower() if "youtube.com" in host or "youtu.be" in host: return "youtube" if "tiktok.com" in host: return "tiktok" if "instagram.com" in host: return "instagram" return None ``` ### Technical Analysis The function identifies supported platforms through substring comparisons against the URL authority. This does not establish that the URL belongs to the expected domain. Attacker-controlled domains such as the following pass validation: - `https://youtube.com.attacker.example/@creator` - `https://fakeinstagram.com/profile` - `https://tiktok.com.evil.example/@creator` The use of `netloc` also includes user-information and port components. For example, a URL with `youtube.com` in its user-information section could be misclassified even when its actual hostname is unrelated. After classification, `validate_profile_url()` considers the URL a supported creator profile. The URL can subsequently be transmitted to the AIsa email-lookup API: ```python def lookup_email(url: str) -> dict[str, Any]: return response_data(post_json(EMAIL_LOOKUP_PATH, {"url": url})) ``` The local script does not directly fetch the submitted profile URL, so this is not a confirmed local SSRF vulnerability. However, it permits unintended URLs to cross the documented trust boundary and be processed by the external API. ### Attack Path 1. An attacker supplies a URL containing a trusted platform name as a substring of an attacker-controlled hostname. 2. `profile_platform()` incorrectly classifies it as YouTube, TikTok, or Instagram. 3. `validate_profile_url()` accepts it as a creator profile URL. 4. `lookup_email()` places the attacker-controlled URL in ...[truncated 830 chars]- Remediation
View remediation
bool: return host == domain or host.endswith("." + domain) def profile_platform(url: str) -> str | None: parsed = urllib.parse.urlsplit(url) host = (parsed.hostname or "").lower().rstrip(".") if parsed.username is not None or parsed.password is not None: return None if parsed.port not in (None, 80, 443): return None if is_domain_or_subdomain(host, "youtube.com") or host == "youtu.be": return "youtube" if is_domain_or_subdomain(host, "tiktok.com"): return "tiktok" if is_domain_or_subdomain(host, "instagram.com"): return "instagram" return None ``` Where practical, narrow the allowlist further to known profile-serving hosts such as `www.youtube.com`, `www.tiktok.com`, and `www.instagram.com`. ]]>
