T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/tools/toolkits.py:71
- Finding
- Unrestricted forwarding of user-controlled URLs to a third-party content extraction service<![CDATA[ ## Vulnerability Details **File Location**: `scripts/tools/toolkits.py:71-84`, with the network request implemented in `scripts/utils/content_extractor.py:65-103` **Vulnerability Type**: Unvalidated URL forwarding and sensitive URL disclosure **Risk Level**: Medium ### Vulnerable Code ```python def fetch_news_content(self, url: str) -> str: """ 使用 Jina Reader 抓取指定 URL 的网页正文内容。 Args: url: 需要抓取内容的完整网页 URL,必须以 http:// 或 https:// 开头。 Returns: 提取的网页正文内容,如果失败则返回错误信息。 """ content = self._news_tools.fetch_news_content(url) if content: return content[:5000] return "内容抓取失败" ``` The URL is subsequently forwarded by the content extractor: ```python @classmethod def extract_with_jina(cls, url: str, timeout: int = 30) -> Optional[str]: if not url or not url.startswith("http"): return None headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/131.0.0.0 Safari/537.36", "Accept": "application/json" } api_key = os.getenv("JINA_API_KEY") has_api_key = bool(api_key and api_key.strip()) if has_api_key: headers["Authorization"] = f"Bearer {api_key}" cls._wait_for_rate_limit(has_api_key) try: full_url = f"{cls.JINA_BASE_URL}{url}" response = requests.get(full_url, headers=headers, timeout=timeout) ``` ### Technical Analysis The exposed `fetch_news_content` tool accepts a URL that may be selected from agent or user-controlled input. Validation consists only of checking whether the string starts with `http`. It does not: - Require a properly parsed `https` URL. - Reject embedded usernames or passwords. - Reject signed URLs or sensitive query-string parameters. - Restrict destination domains to approved news sources. - Reject localhost, private, reserved, link-local, or metadata-service addresses. - Account ...[truncated 1998 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse URLs with `urllib.parse.urlsplit` instead of using a prefix check. 2. Permit only the exact `https` scheme. 3. Maintain an allowlist of approved public financial-news domains. 4. Reject URLs containing username or password components. 5. Remove or reject sensitive query parameters such as `token`, `key`, `signature`, `credential`, and `auth`. 6. Resolve destination hostnames and reject loopback, private, link-local, multicast, reserved, and unspecified IP ranges. 7. Revalidate every redirect destination or disable redirects. 8. Require explicit user confirmation before forwarding a URL outside the local environment. 9. Clearly disclose that Jina receives the complete URL. 10. Prefer direct requests to approved public sources where licensing and security policies allow them. 11. Add tests for malformed schemes, encoded hostnames, IPv6 literals, redirect chains, embedded credentials, and private addresses. ]]>
