T09 · Insecure Skill Coding Practices
- Location
scripts/parse_share.py:28- Finding
Unanchored URL Validation Allows Arbitrary Browser Navigation and SSRF
- Content
View full analysis
str: for pat in CHATGPT_PATTERNS: if pat.search(url): return "chatgpt" for pat in GEMINI_PATTERNS: if pat.search(url): return "gemini" return "" ``` The accepted string is subsequently used as the browser navigation destination: ```python await page.goto(url, wait_until="domcontentloaded", timeout=timeout * 1000) ``` Redirect validation is incomplete: ```python current_url = page.url if "share_not_found" in current_url or "not_found" in current_url: await browser.close() print("分享链接已过期或不存在。", file=sys.stderr) sys.exit(2) if platform == "chatgpt" and "/share/" not in current_url and "/s/t_" not in current_url: await browser.close() print( f"页面被重定向到 {current_url},分享链接可能已过期或需要登录。", file=sys.stderr, ) sys.exit(2) ``` ### Technical Analysis The validation expressions are used with `re.Pattern.search()`, so an approved URL only needs to occur somewhere inside the input. The code does not parse the URL or verify that its actual hostname is an approved ChatGPT or Gemini host. For example, the following input is classified as ChatGPT even though its real destination is a loopback service: ```text http://127.0.0.1:8080/?source=https://chatgpt.com/share/example ``` Because the full, attacker-controlled string is passed to `page.goto()`, Chromium navigates to `127.0.0.1`, not `chatgpt.com`. The post-navigation controls do not eliminate this issue. ...[truncated 1969 chars]- Remediation
View remediation
str: parsed = urlsplit(url) if parsed.scheme != "https" or parsed.username or parsed.password: return "" host = (parsed.hostname or "").rstrip(".").lower() prefixes = ALLOWED_PATHS.get(host) if not prefixes or not any(parsed.path.startswith(p) for p in prefixes): return "" if host in {"chatgpt.com", "chat.openai.com"}: return "chatgpt" return "gemini" ``` The same hostname, address-range, and path validation must be applied to the final URL and all intermediate redirects before their content is trusted. ]]>
