T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/fetch_asset.py:20
- Finding
- Unrestricted Remote Asset Retrieval and Arbitrary File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fetch_asset.py:20-32` **Vulnerability Type**: Unrestricted URL retrieval, SSRF, and arbitrary file overwrite **Risk Level**: High ### Vulnerable Code ```python def main(argv: list[str]) -> int: ap = argparse.ArgumentParser(prog="fetch_asset") ap.add_argument("--url", required=True) ap.add_argument("--out", required=True) args = ap.parse_args(argv) out_path = pathlib.Path(args.out) out_path.parent.mkdir(parents=True, exist_ok=True) req = urllib.request.Request(args.url, headers={"User-Agent": "openclaw-radarr-skill"}) with urllib.request.urlopen(req, timeout=60) as resp: data = resp.read() out_path.write_bytes(data) ``` ### Technical Analysis The script accepts an unrestricted source URL and unrestricted destination path. Although the documented use is to retrieve a poster from TMDB and place it under an outbound directory, the implementation does not enforce either constraint. `urllib.request.urlopen()` can access arbitrary network destinations and follows HTTP redirects. There is no validation of the URL scheme, hostname, resolved IP address, redirect destination, response content type, or response size. This can allow server-side request forgery against loopback, private-network, link-local, or cloud metadata services reachable from the Agent host. The output path is also used directly. `Path.write_bytes()` truncates and overwrites an existing file if the process has permission. There is no resolved-path containment check, symlink protection, exclusive file creation, or restriction to the documented outbound directory. The response is read entirely into memory without a size limit and can then consume local disk space. These capabilities exceed the minimum privileges required to download a TMDB poster. ### Attack Path 1. An attacker supplies or causes the Agent to use a crafted asset URL instead of a legitimate TMDB image URL. 2. The Agent i ...[truncated 1173 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Restrict downloads to HTTPS and an explicit hostname allowlist, such as `image.tmdb.org`. 2. Resolve hostnames and reject loopback, private, link-local, multicast, reserved, and unspecified IP addresses. 3. Disable redirects or validate every redirect destination using the same scheme, host, and IP restrictions. 4. Reject URLs containing embedded credentials and unsupported ports. 5. Resolve the destination path and verify that it remains under a dedicated directory such as `outbound/radarr/`. 6. Reject absolute paths, parent-directory traversal, and symlinks. 7. Use exclusive file creation or an explicit safe-overwrite policy. 8. Stream the response while enforcing a conservative maximum byte count. 9. Require an expected image content type and validate the downloaded file as an image before saving it. 10. Apply restrictive file permissions and remove partially downloaded files when validation fails. ]]>
