T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/send.mjs:52
- Finding
- Unrestricted Remote URL Fetching Enables SSRF and Resource Exhaustion## Vulnerability Details **File Location**: `scripts/send.mjs`, lines 52–58 **Vulnerability Type**: Server-Side Request Forgery (SSRF) and unbounded resource consumption **Risk Level**: Medium ### Vulnerable Code ```js async function loadFile(source) { if (/^https?:\/\//.test(source)) { const res = await fetch(source); if (!res.ok) throw new Error(`HTTP ${res.status} fetching ${source}`); const buf = Buffer.from(await res.arrayBuffer()); const name = basename(new URL(source).pathname) || "file.bin"; return { buf, name }; } ``` ### Technical Analysis The `--files` argument accepts arbitrary HTTP and HTTPS URLs. The script passes each URL directly to `fetch()` without validating its destination hostname, resolved IP address, port, or URL scheme beyond the initial regular expression. Consequently, an authorized caller able to invoke the Skill can direct the host to request loopback, link-local, private-network, cloud metadata, or other otherwise inaccessible endpoints. Redirects are followed by `fetch()` by default, but redirect destinations are not revalidated. Although the documentation advertises HTTPS URLs, the implementation also permits plaintext HTTP. The response is read in full with `res.arrayBuffer()` and then copied into a `Buffer`. No request timeout, response-size ceiling, attachment-count limit, or aggregate-memory limit is applied. A large or slow response can therefore consume substantial memory and execution resources. ### Attack Path 1. An attacker or untrusted caller supplies a URL through `--files`, such as a loopback/private-network endpoint or a public URL that redirects to one. 2. `loadFile()` passes that URL directly to `fetch()`. 3. The process accesses the target using the host's network position and follows redirects without destination validation. 4. The complete response is loaded into process memory. 5. The response is packaged as an attachment and sent to ...[truncated 931 chars]
- Remediation
- ## Remediation Suggestions - Permit only HTTPS URLs unless plaintext HTTP is explicitly required. - Parse URLs with the standard `URL` API and reject embedded credentials, unexpected ports, malformed hostnames, and unsupported schemes. - Resolve hostnames before connecting and reject loopback, link-local, private, multicast, reserved, and cloud-metadata address ranges for both IPv4 and IPv6. - Disable automatic redirects or manually process them, applying the same validation to every redirect destination. - Add an `AbortController`-based connection and total-request timeout. - Validate `Content-Length` when available and enforce a streaming byte limit regardless of whether the header is present. - Enforce per-file, attachment-count, and aggregate-download size limits. - Prefer an explicit allowlist of trusted download domains where operationally practical. - Avoid holding every attachment in memory concurrently; use bounded concurrency and streaming or temporary files with secure permissions where supported. - Ensure destination authorization is checked before fetching remote content so unauthorized recipients cannot be used as exfiltration channels.
