T09 · Insecure Skill Coding Practices
- Location
scripts/fetch-board.mjs:3- Finding
Unrestricted Base URL Enables Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
scripts/fetch-board.mjs, lines 3–7
Vulnerability Type: Server-Side Request Forgery through an unvalidated command-line URL
Risk Level: MediumVulnerable Code
js const baseUrl = (process.argv[2] || 'https://marsedge.vip').replace(/\/$/, ''); const url = `${baseUrl}/api/probboard/latest`; try { const res = await fetch(url, {Technical Analysis
The script permits its first command-line argument to determine the request origin without validating the URL scheme, hostname, resolved IP address, embedded credentials, or destination network range. Node.js
fetchalso follows HTTP redirects by default.An attacker who can influence the argument can therefore cause the runtime to issue a request to an attacker-selected host, including potentially localhost, private-network services, or link-local infrastructure. An attacker-controlled endpoint could also redirect the request to another destination.
The script reads the entire response using
res.text(). If the response is not JSON, up to 500 characters are included in error output. Valid JSON error responses may be emitted through thedatafield. This creates a limited channel through which content obtained from an unintended destination can become visible in script or agent output. Reading the response without a size limit also exposes the process to memory exhaustion from an oversized response.Attack Path
- An attacker directly supplies, or persuades an agent or operator to supply, a malicious base URL as the first command-line argument.
- The script appends
/api/probboard/latestand sends a request to that origin. - The supplied server may respond directly or redirect the request toward a localhost, private-network, or link-local service.
- The script reads the destination's response without a response-size limit.
- Depending on the response format and status, response content is printed in an error object or processed as ...[truncated 772 chars]
- Remediation
View remediation
Remediation Suggestions
- Remove the base URL override if requests are only intended for
marsedge.vip. - If configurability is required, parse the input with
URLand enforce:- The
https:protocol. - An explicit allowlist of approved hostnames.
- No embedded username or password.
- The expected port or a narrow allowlist of ports.
- The
- Resolve the hostname and reject loopback, private, link-local, multicast, reserved, and cloud-metadata address ranges for both IPv4 and IPv6. Repeat destination validation when establishing the connection to reduce DNS rebinding risk.
- Disable automatic redirects with
redirect: 'manual', or validate the scheme, hostname, port, and resolved address of every redirect target before following it. - Add an
AbortSignaltimeout to prevent slow or stalled requests from tying up the process. - Stream the response while enforcing a strict byte limit instead of calling
res.text()on an unbounded body. - Avoid printing arbitrary response bodies. Return a fixed error message or a tightly sanitized and size-limited diagnostic.
- Validate the expected response schema and field types before emitting the resulting JSON.
- Remove the base URL override if requests are only intended for
