T09 · Insecure Skill Coding Practices
- Location
scripts/download.py:20- Finding
Unrestricted Browser Navigation Enables Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
scripts/download.py, lines 20-54
Vulnerability Type: Unvalidated URL navigation / server-side request forgery
Risk Level: HighVulnerable Code
python def download(video_url, output_path, cookie_file): os.environ['HTTPS_PROXY'] = PROXY os.environ['HTTP_PROXY'] = PROXY from playwright.sync_api import sync_playwright pw_cookies = load_cookies(cookie_file) print(f"Loaded {len(pw_cookies)} Douyin cookies") video_url_found = [None] def handle_response(response): url = response.url if video_url_found[0]: return if 'douyinvod.com' in url and ('video/tos' in url or 'video/m/v' in url): video_url_found[0] = url print(f"Video URL intercepted: {url[:80]}...") with sync_playwright() as p: browser = p.chromium.launch(headless=True) ctx = browser.new_context( user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36' ) for c in pw_cookies: try: ctx.add_cookies([c]) except Exception as e: pass page = ctx.new_page() page.on('response', handle_response) print(f"Loading {video_url} ...") page.goto(video_url, wait_until='domcontentloaded', timeout=30000)Technical Analysis
The caller-controlled
video_urlis passed directly to Playwright'spage.goto()without validating its scheme, hostname, port, resolved address, or redirect destination. Nothing requires the destination to be an HTTPS Douyin or TikTok page.Playwright therefore acts as a network-capable browser under the privileges and network visibility of the process running the Skill. A supplied URL can target loopback addresses, private network ranges, link-local services, or arbitrary Internet hosts. An a ...[truncated 2500 chars]
- Remediation
View remediation
Remediation Suggestions
- Parse the input with
urllib.parse.urlparseand accept onlyhttpsURLs. - Allowlist exact legitimate hostnames and carefully defined subdomains of Douyin and TikTok. Compare normalized hostnames rather than searching the entire URL for a substring.
- Reject URLs containing embedded credentials, unsupported ports, malformed internationalized hostnames, or IP-address literals.
- Resolve the hostname and reject loopback, private, link-local, multicast, reserved, and unspecified IP ranges for both IPv4 and IPv6.
- Validate every redirect destination before allowing navigation to continue. Playwright request routing can abort navigation or subresource requests to disallowed origins.
- Apply an outbound network allowlist to browser requests so attacker-controlled pages cannot contact internal services.
- Load account cookies only after the initial URL and redirect chain have been validated.
- Use a dedicated, least-privileged browser environment with restricted network access and no access to local administrative interfaces.
- Fail closed when URL parsing, DNS resolution, or destination validation is ambiguous.
- Parse the input with
