{"record":{"id":"5316b013c7c6bd4f","repo":"ruvnet/ruflo","slug":"invalid-or-unsafe-url-only-https-is-supported","errorCode":null,"errorMessage":"Invalid or unsafe URL (only HTTPS is supported)","messagePattern":"Invalid or unsafe URL \\(only HTTPS is supported\\)","errorType":"http","errorClass":"HttpError","httpStatus":400,"severity":"error","filePath":"ruflo/src/ruvocal/src/routes/api/fetch-url/+server.ts","lineNumber":59,"sourceCode":"\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn callback(null, address, family);\n\t\t\t});\n\t\t},\n\t},\n});\n\nexport async function GET({ url }) {\n\tconst targetUrl = url.searchParams.get(\"url\");\n\n\tif (!targetUrl) {\n\t\tlogger.warn(\"Missing 'url' parameter\");\n\t\tthrow error(400, \"Missing 'url' parameter\");\n\t}\n\n\tif (!isValidUrl(targetUrl)) {\n\t\tlogger.warn({ targetUrl }, \"Invalid or unsafe URL (only HTTPS is supported)\");\n\t\tthrow error(400, \"Invalid or unsafe URL (only HTTPS is supported)\");\n\t}\n\n\t// Fetch with timeout, following redirects manually to validate each hop\n\tconst controller = new AbortController();\n\tconst timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT);\n\n\tlet currentUrl = targetUrl;\n\tlet response: Awaited<ReturnType<typeof fetch>>;\n\tlet redirectCount = 0;\n\n\ttry {\n\t\t// eslint-disable-next-line no-constant-condition\n\t\twhile (true) {\n\t\t\tresponse = await fetch(currentUrl, {\n\t\t\t\tsignal: controller.signal,\n\t\t\t\tredirect: \"manual\",\n\t\t\t\tdispatcher: ssrfSafeAgent,\n\t\t\t\theaders: {","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/ruflo/src/ruvocal/src/routes/api/fetch-url/+server.ts#L41-L77","documentation":"SvelteKit 400 error thrown by the fetch-url GET handler when the provided URL fails isValidUrl — the endpoint only permits HTTPS and blocks unsafe targets as an SSRF guard.","triggerScenarios":"Thrown at ruflo/src/ruvocal/src/routes/api/fetch-url/+server.ts:59 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Provide a valid https:// URL pointing to a public host; private IPs, localhost, and non-HTTPS schemes are rejected by the SSRF guard."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}