T09 · Insecure Skill Coding Practices
- Location
scripts/send.mjs:52- Finding
Unrestricted Remote URL Fetching Enables SSRF and Resource Exhaustion
- Content
View full analysis
Vulnerability Details
File Location:
scripts/send.mjs, lines 52–58
Vulnerability Type: Server-Side Request Forgery (SSRF) and unbounded resource consumption
Risk Level: MediumVulnerable 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
--filesargument accepts arbitrary HTTP and HTTPS URLs. The script passes each URL directly tofetch()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 aBuffer. 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
- 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. loadFile()passes that URL directly tofetch().- The process accesses the target using the host's network position and follows redirects without destination validation.
- The complete response is loaded into process memory.
- The response is packaged as an attachment and sent to ...[truncated 931 chars]
- An attacker or untrusted caller supplies a URL through
- Remediation
View remediation
Remediation Suggestions
- Permit only HTTPS URLs unless plaintext HTTP is explicitly required.
- Parse URLs with the standard
URLAPI 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-Lengthwhen 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.
