T09 · Insecure Skill Coding Practices
- Location
scripts/venice-upscale.py:113- Finding
Unrestricted URL Fetching Enables Server-Side Request Forgery and Data Disclosure
- Content
View full analysis
str: """Download an HTTP(S) URL and return as raw base64 string.""" req = urllib.request.Request(url, headers={"User-Agent": USER_AGENT}) with urllib.request.urlopen(req, timeout=60) as resp: data = resp.read() return base64.b64encode(data).decode("ascii") def upscale_image_from_url( api_key: str, image_url: str, scale: int = 2, enhance: bool = False, enhance_prompt: str | None = None, enhance_creativity: float | None = None, replication: float | None = None, ) -> bytes: """ Upscale an image via Venice API using a URL or base64 data URL. HTTP(S) URLs are downloaded and converted to base64 first. Returns raw image bytes. """ # API requires base64, not HTTP URLs if image_url.startswith(("http://", "https://")): image_url = _fetch_url_as_base64(image_url) ``` ### Technical Analysis The `--url` argument is treated as a trusted network location after checking only that its textual value begins with `http://` or `https://`. The process then fetches the supplied address from its own network context. No controls prevent requests to: - Loopback addresses such as `127.0.0.1` or `[::1]` - RFC 1918 private networks - Link-local addresses - Cloud instance metadata services - Internal DNS names - Reserved or otherwise non-public address ranges `urllib.request.urlopen` follows HTTP redirects by default, but redirect destinations are not revalidated. An initially public URL can consequently redirect to an internal address. The response is also consumed with an unrestricted `resp.read()`. There is no `Content-Length` limit, streaming limit, image MIME-type verification, ...[truncated 2191 chars]- Remediation
View remediation
