{"record":{"id":"7284f2e5838a4ff9","repo":"diegosouzapw/OmniRoute","slug":"outbound-url-guard-blocked-7284f2","errorCode":"OUTBOUND_URL_GUARD_BLOCKED","errorMessage":"Blocked cloud-metadata catalog URL (SSRF protection)","messagePattern":"Blocked cloud-metadata catalog URL \\(SSRF protection\\)","errorType":"exception","errorClass":"OutboundUrlGuardError","httpStatus":null,"severity":"error","filePath":"src/lib/cli-helper/config-generator/opencode.ts","lineNumber":25,"sourceCode":"} from \"../../../shared/network/outboundUrlGuard\";\nimport { resolveOpencodeConfigPath } from \"../../../shared/services/opencodeConfigPath\";\n\nconst JSON_FORMATTING_OPTIONS = { insertSpaces: true, tabSize: 2 } as const;\n\n/**\n * SSRF guard for the catalog fetch (CodeQL js/request-forgery #326). The catalog\n * source is the user's OWN OmniRoute instance, so loopback/private hosts are the\n * legitimate default and must stay allowed — we cannot use the public-only guard\n * here. What has NO legitimate use as a catalog source is the cloud-metadata /\n * link-local pivot (169.254.169.254, metadata.google.internal, …): that is the\n * classic SSRF→IAM-credential escalation and is blocked unconditionally, along\n * with non-http(s) protocols and embedded credentials (via parseOutboundUrl).\n */\nexport function assertSafeCatalogUrl(rawUrl: string): URL {\n  const url = parseOutboundUrl(rawUrl); // throws on bad protocol / embedded creds\n  if (isCloudMetadataHost(url.hostname)) {\n    throw new OutboundUrlGuardError(\"Blocked cloud-metadata catalog URL (SSRF protection)\", {\n      code: \"OUTBOUND_URL_GUARD_BLOCKED\",\n      url: url.toString(),\n      hostname: url.hostname,\n    });\n  }\n  // Return the re-parsed URL so callers fetch the validated value (a `new URL()`\n  // round-trip is a recognized request-forgery barrier — clears CodeQL #326).\n  return url;\n}\n\n/**\n * OpenAI-compatible model entry — subset of fields the /v1/models endpoint\n * returns. Only the fields we need to emit `limit.context` / `limit.output`\n * are typed.\n */\ninterface CatalogModelEntry {\n  id: string;\n  owned_by?: string;\n  /** OpenAI-compatible field name; some upstreams return this. */","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/diegosouzapw/OmniRoute/blob/a179ffed5bb2e0b883b9ae7214ce8717b2a94c4d/src/lib/cli-helper/config-generator/opencode.ts#L7-L43","documentation":"Error \"Blocked cloud-metadata catalog URL (SSRF protection)\" thrown in diegosouzapw/OmniRoute.","triggerScenarios":"Thrown at src/lib/cli-helper/config-generator/opencode.ts:25 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":[],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"a179ffed5bb2e0b883b9ae7214ce8717b2a94c4d","analyzedAt":"2026-08-25T18:35:09.898Z","schemaVersion":2},"datasetVersion":"2026-08-25T21:54:21.419Z"}