T09 · Insecure Skill Coding Practices
- Location
src/geo_content_writer/citation_crawl.py:11- Finding
Unrestricted citation crawling enables server-side request forgery
- Content
View full analysis
List[Dict[str, Any]]: pages: List[Dict[str, Any]] = [] article_count = 0 for url in urls[:max_candidates]: try: response = requests.get( url, timeout=timeout, headers={ "User-Agent": "Mozilla/5.0 (compatible; GEOContentWriter/1.0; +https://github.com/GEO-SEO/geo-content-writer)" }, ) response.raise_for_status() html = response.text ``` The URL values are taken from citation records and passed directly to the crawler: ```python citation_urls = _diversified_citation_urls(context.get("citations", []), limit=citation_limit) crawled_pages = crawl_citation_pages(citation_urls, limit=citation_limit) ``` The URL extraction logic does not perform security validation: ```python def _top_citation_urls(citations: List[Dict[str, Any]], limit: int = 5) -> List[str]: urls: List[str] = [] for item in _top(citations, "citationCount", limit): url = (item.get("url") or "").strip() if url: urls.append(url) return urls ``` ### Technical Analysis The crawler makes outbound requests to citation URLs without validating: - The URL scheme - The resolved IP address - Whether the destination is loopback, private, link-local, reserved, or multicast - The destination port - DNS rebinding between validation and connection - Redirect destinations - Response size or content type `requests.get()` follows redirects by default. Consequently, validating only an in ...[truncated 1942 chars]- Remediation
View remediation
