SSRF error disclosure enables internal network and port enumeration via /api/fetch
info-leak · server.js:72-72
f87c6fc2fa by Macintosh1011 on 2026-05-30Summary
The /api/fetch endpoint forwards raw Node.js network error messages from the outbound HTTP request directly to the client in a 502 response (server.js:72). Different failure modes (ECONNREFUSED, EHOSTUNREACH, ETIMEDOUT, ENOTFOUND, TLS handshake errors, etc.) each yield distinguishable error strings, so attackers can differentiate closed ports, filtered ports, live hosts, and unresolved names. Combined with the server-side fetch capability, this turns the endpoint into a precise internal-network probing tool.
Impact. An unauthenticated attacker can map the server's internal network: by iterating over IPs and ports in url= parameters and observing the distinct error messages returned (e.g., 'connect ECONNREFUSED 127.0.0.1:1' versus a timeout versus a DNS failure), they can enumerate live hosts, open/closed/filtered ports, and internal service identities. This significantly accelerates lateral-movement reconnaissance against cloud metadata services, internal admin panels, and other non-public infrastructure reachable from the server.
Vulnerable code — server.js
🔴 .on("error", (e) => send(res, 502, `fetch error: ${e.message}`));
Working exploit
curl -s 'http://127.0.0.1:4600/api/fetch?url=http://127.0.0.1:1/'
Exploit transcript
HTTP 502 Content-Type: text/plain fetch error: connect ECONNREFUSED 127.0.0.1:1
Confirmed: HTTP 502 text/plain body: 'fetch error: connect ECONNREFUSED 127.0.0.1:1'
CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N→ 5.3 (medium)Recommended fix
AI-suggested fix — review before applying (derived from analysis of untrusted repo content):
Return a generic error to clients and log details server-side only:
--- a/server.js
+++ b/server.js
@@
- .on("error", (e) => send(res, 502, `fetch error: ${e.message}`));
+ .on("error", (e) => {
+ console.error("upstream fetch error", { url, code: e.code, msg: e.message });
+ send(res, 502, "upstream fetch failed");
+ });
Additionally, enforce an allow-list of permitted hosts/schemes and block RFC1918, loopback, link-local, and metadata IPs before initiating the request to mitigate the underlying SSRF.Ship the fix
Rook found it and proved it. Hand the finding — with its working exploit as a failing test — to Otis to write the fix PR.