T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- bb-sites/gumtree/listing.js:68
- Finding
- Server-Side Request Forgery Through an Unrestricted Listing URL## Vulnerability Details **File Location**: `bb-sites/gumtree/listing.js`, lines 68-79 **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: High ### Vulnerable Code ```js if (!args.url) return { error: 'Missing argument: url', hint: 'e.g. bb-browser site gumtree/listing "https://www.gumtree.com/p/.../ID"' }; let path = String(args.url).trim(); if (!path.startsWith('http')) { if (!path.startsWith('/')) path = '/' + path; path = 'https://www.gumtree.com' + path; } const resp = await fetch(path, { ``` ### Technical Analysis The adapter accepts an absolute URL from `args.url` and passes it directly to `fetch()` whenever its string begins with `http`. It does not parse the URL, restrict the protocol, validate the hostname, resolve and inspect the destination IP address, or enforce the declared `www.gumtree.com` domain. As a result, an attacker who can control the listing URL can cause the Agent environment to send requests to arbitrary Internet hosts, localhost services, private network addresses, link-local endpoints, or potentially cloud instance metadata services. The default redirect behavior can also permit a nominally allowed URL to redirect to an unauthorized destination. The fetched response is processed for JSON-LD and Open Graph metadata. Parseable title, description, image, pricing, or location data can therefore be returned to the caller. Even when response contents are not extractable, HTTP status codes and the final redirect URL may provide an internal-service discovery oracle. ### Attack Path 1. An attacker supplies an absolute URL such as `http://127.0.0.1:PORT/path`, a private network endpoint, or a link-local metadata endpoint as `args.url`. 2. The value begins with `http`, so the code accepts it without adding or enforcing the Gumtree hostname. 3. `fetch(path)` sends the request from the Agent's network environment. 4. The target response is read and parsed as HTML. 5 ...[truncated 832 chars]
- Remediation
- ## Remediation Suggestions - Parse the supplied value using `new URL()` rather than relying on `startsWith('http')`. - Require the `https:` protocol. - Permit only `www.gumtree.com` and any other explicitly reviewed Gumtree hostnames. - Reject URLs containing embedded credentials, unexpected ports, malformed hostnames, or hostname suffix tricks. - Resolve the hostname before making the request and reject loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 ranges. - Disable automatic redirects or validate every redirect destination using the same protocol, hostname, port, and resolved-address rules. - Prefer accepting only a Gumtree path or listing identifier and constructing the complete URL internally. - Apply request timeouts, response-size limits, and content-type checks to reduce secondary denial-of-service risks. Example defensive approach: ```js const base = new URL('https://www.gumtree.com/'); const target = new URL(String(args.url).trim(), base); if (target.protocol !== 'https:' || target.hostname !== 'www.gumtree.com') { return { error: 'Only HTTPS URLs on www.gumtree.com are permitted' }; } const resp = await fetch(target.href, { redirect: 'manual', headers: { Accept: 'text/html,application/xhtml+xml' } }); ``` This example must be supplemented with redirect validation and resolved-IP filtering when the runtime permits DNS resolution or when DNS rebinding is within the threat model.
