T09 · Insecure Skill Coding Practices
- Location
runtime/src/dpp_storyboard/composition_service.py:158- Finding
Unrestricted Download of a Remotely Supplied Generated-Asset URL
- Content
View full analysis
Path: output_path.parent.mkdir(parents=True, exist_ok=True) with urllib.request.urlopen(url, timeout=120) as response, output_path.open("wb") as destination: shutil.copyfileobj(response, destination) return output_path ``` ```python def _download_generated_video( self, *, video_url: str | None, target_dir: Path, task_id: str, ) -> str | None: if not video_url: return None suffix = Path(urlparse(video_url).path).suffix or ".mp4" output_path = target_dir / "generated" / f"{task_id}{suffix}" try: downloaded = self._downloader.download_video(url=video_url, output_path=output_path) except Exception as exc: logger.warning("Failed to download generated video for task %s: %s", task_id, exc) return None return str(downloaded.resolve()) ``` ### Technical Analysis The downloader consumes `video_url` from a remote Ark task response and passes it directly to `urllib.request.urlopen`. It does not validate: - The URL scheme. - The destination hostname. - The resolved IP address. - Redirect destinations. - Whether the destination is loopback, link-local, private, multicast, or reserved. - The response content type. - The response body size. Consequently, a compromised or attacker-controlled Ark-compatible service can return a URL targeting an internal network service, loopback interface, cloud metadata endpoint, or another sensitive destination accessible from the machine running the Skill. Since `urllib` supports redirects, validating only the initial URL would also be insufficient. The use of `shutil.copyfileobj` w ...[truncated 1269 chars]- Remediation
View remediation
