T09 · Insecure Skill Coding Practices
Error
- Location
- reslib/cli.py:539
- Finding
- Unrestricted Remote Document Retrieval Enables Server-Side Request Forgery and Resource Exhaustion<![CDATA[ ## Vulnerability Details **File Location**: `reslib/cli.py:283-289` and `reslib/cli.py:539-552` **Vulnerability Type**: Server-Side Request Forgery (SSRF) and unbounded remote download **Risk Level**: High ### Vulnerable Code ```python def is_url(s: str) -> bool: """Check if a string is a URL.""" try: result = urlparse(s) return result.scheme in ("http", "https", "ftp") except Exception: return False ``` ```python if is_url(path): source_url = path # Download the file if not quiet and not json_output: echo_info(f"Downloading from {path}...") try: import urllib.request import tempfile # Create temp file with appropriate extension parsed = urlparse(path) ext = Path(parsed.path).suffix or ".bin" with tempfile.NamedTemporaryFile(suffix=ext, delete=False) as tmp: urllib.request.urlretrieve(path, tmp.name) file_path = Path(tmp.name) except Exception as e: echo_error(f"Failed to download: {e}") ctx.exit(1) ``` ### Technical Analysis The `add` command retrieves a user-supplied URL without validating its destination. The implementation accepts HTTP, HTTPS, and FTP URLs, but does not: - Reject loopback, link-local, private, multicast, or reserved IP addresses. - Block cloud instance metadata endpoints. - Validate DNS resolutions before connecting. - Revalidate destinations after HTTP redirects. - Apply explicit connection or read timeouts. - Impose a maximum response or downloaded-file size. - Restrict remote retrieval to approved domains. Consequently, a caller can direct the process to request services that are reachable from the machine running the CLI but are not reachable from the caller's own network position. Redirects and DNS rebinding may also bypass checks if only the original URL is validated in a future partial fix. Because the downloaded response is subsequently hashed, copied into the attac ...[truncated 2009 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Disable remote ingestion by default and require an explicit option to enable it. 2. Permit only HTTPS, or HTTP and HTTPS when HTTP is operationally necessary. Remove FTP support. 3. Resolve the hostname before connecting and reject every address in loopback, private, link-local, multicast, unspecified, and reserved ranges. 4. Apply the same hostname and IP validation after every redirect. 5. Prevent DNS rebinding by connecting to a validated resolved address while preserving correct TLS hostname verification. 6. Configure short connection and read timeouts. 7. Stream downloads in fixed-size chunks instead of using `urlretrieve()`. 8. Abort when the response exceeds a configured maximum size. 9. Validate `Content-Length` when present, but do not rely on it as the sole size control. 10. Consider an allowlist of trusted hosts for environments where remote ingestion is required. 11. Ensure partially downloaded temporary files are deleted in a `finally` block. 12. Add tests covering loopback addresses, IPv6 loopback, private ranges, link-local metadata endpoints, redirects to private addresses, DNS rebinding scenarios, timeouts, and oversized responses. ]]>
