#2280·refly

Server-Side Request Forgery in misc/scrape weblink endpoint

Author: geo-chenCreated Jun 15, 2026Updated Jun 15, 2026

The endpoint POST /v1/misc/scrape (apps/api/src/modules/misc/misc.controller.ts) takes a url field from the request body and passes it directly to the shared scrapeWeblink utility (packages/utils/src/scrape-weblink.ts), which calls fetch() on it with no validation of the scheme, host, or resolved IP address and follows redirects. The fetched page's title and meta description are then returned in the response.

Any registered user (email signup is enabled by default) can therefore make the backend issue HTTP requests to internal-only addresses such as cloud metadata services, internal dashboards, or other services on the deployment network, and read back the page title and description. I confirmed the behavior by running the exact scrapeWeblink logic against a local internal-only HTTP server: the request reached it and the server's internal title and meta description were returned to the caller. The same unguarded fetch() is also reachable through dumpFileFromURL when re-hosting markdown image URLs, which stores the full response body.

Suggested fix: Before fetching, resolve the target hostname and reject requests whose resolved IP falls in private, loopback, link-local, or cloud-metadata ranges (including IPv4-mapped IPv6 and 0.0.0.0); restrict the scheme to http/https; and re-validate the destination after each redirect (or disable redirects) to prevent DNS-rebinding and redirect-based bypasses. Apply the same guard centrally so both the scrape endpoint and dumpFileFromURL are covered.