T09 · Insecure Skill Coding Practices
- Location
scripts/pexels.ts:107- Finding
Unrestricted Pexels Download URL Enables SSRF and Arbitrary File Overwrite
- Content
View full analysis
{ const resp = await fetch(url, { headers: { "User-Agent": "PexelsCLI/0.1" }, }); if (!resp.ok) { console.error(`Download failed - HTTP ${resp.status}`); process.exit(1); } const buf = await resp.arrayBuffer(); await Bun.write(output, new Uint8Array(buf)); console.error(`Downloaded: ${output}`); } ``` ```ts async function download(flags: Record) { if (!flags["--url"]) { console.error("Error: --url is required"); process.exit(1); } if (!flags["--output"]) { console.error("Error: --output is required"); process.exit(1); } await downloadFile(flags["--url"], flags["--output"]); } ``` ### Technical Analysis The `download` command passes a caller-controlled URL directly to `fetch`. It does not enforce HTTPS, restrict downloads to Pexels media hosts, resolve and reject non-public addresses, or validate redirect destinations. Consequently, the command can make HTTP requests to loopback addresses, private network services, link-local services, or cloud metadata endpoints. This network access exceeds the minimum privilege required to download media returned by Pexels. The caller also fully controls the output path. `Bun.write` can overwrite files writable by the current process, and the implementation does not restrict writes to a designated media directory or reject existing files. ### Attack Path 1. An attacker supplies a URL presented as a Pexels media resource. 2. The Agent invokes `pexels.ts download` with the attacker-controlled `--url`. 3. The script requests an internal target such as a loopback service, private network host, or metadata endpoint. 4. The response is writt ...[truncated 811 chars]- Remediation
View remediation
