T09 · Insecure Skill Coding Practices
- Location
scripts/publish_instagram.py:81- Finding
Arbitrary URL Fetch Enables SSRF and Unintended Data Upload
- Content
View full analysis
Vulnerability Details
File Location:
scripts/publish_instagram.py, lines 81–92, 98–100, and 247–249
Vulnerability Type: Server-Side Request Forgery (SSRF), unrestricted download, and unintended data transfer
Risk Level: HighVulnerable Code
python def _download_to_tempfile(self, url: str) -> Path: response = requests.get(url, stream=True, timeout=300) response.raise_for_status() suffix = Path(url.split("?")[0]).suffix or ".bin" fd, temp_path = tempfile.mkstemp(prefix="instagram_publish_", suffix=suffix) os.close(fd) temp_file = Path(temp_path) with temp_file.open("wb") as handle: for chunk in response.iter_content(chunk_size=8192): handle.write(chunk) return temp_filepython if url: temp_path = self._download_to_tempfile(url) path = str(temp_path)python if item.startswith(("http://", "https://")): child_id = publisher.upload_media_item( media_type, url=item, thumb_offset=args.thumb_offset, wait=args.wait, )Technical Analysis
The carousel workflow accepts an arbitrary HTTP or HTTPS URL and downloads its response from the machine running the Skill. It does not validate the resolved destination or reject loopback, private, link-local, reserved, multicast, or cloud metadata addresses.
The
requestslibrary follows redirects by default. Consequently, validating only the original string prefix does not prevent a public URL from redirecting to an internal destination. DNS rebinding and IPv6 address representations are also not addressed.After downloading the response,
upload_media_item()opens the temporary file and submits its contents to the declared MyBrandMetrics publishing endpoint. An attacker-controlled URL can therefore cause data obtained from a resource accessible to the Skill host to be transferred to an external service.The download loop also has no maximum byte count. Although a network timeout i ...[truncated 1992 chars]
- Remediation
View remediation
Remediation Suggestions
- Permit remote media downloads only over HTTPS unless HTTP support is explicitly required.
- Parse URLs with a standard URL parser and reject embedded credentials, malformed hosts, unsupported ports, and ambiguous address representations.
- Resolve the hostname before connecting and reject every resolved IPv4 and IPv6 address in loopback, private, link-local, multicast, reserved, unspecified, and other non-public ranges.
- Explicitly block cloud metadata destinations, including link-local metadata addresses and provider-specific metadata hostnames.
- Disable automatic redirects or validate the destination of every redirect using the same URL and resolved-address policy.
- Account for DNS rebinding by ensuring the validated address is the address used for the connection, or route downloads through an isolated proxy with strict egress controls.
- Enforce a conservative response-size limit using both
Content-Lengthwhen present and a running byte counter while streaming. Abort and delete the temporary file once the limit is exceeded. - Permit only expected image and video MIME types. Verify file signatures rather than relying on URL extensions or
Content-Typealone. - Apply explicit connection and read timeouts and limit the number of redirects.
- Run the downloader in a network-restricted environment that cannot access internal networks or metadata services.
- Consider avoiding local URL retrieval entirely: pass validated public media URLs to the publishing service where supported.
- Require explicit user confirmation when retrieving media from a previously unapproved domain.
