{"record":{"id":"68626cfc52ac8291","repo":"stablyai/orca","slug":"localhost-label-target-is-not-an-allowed-workspace","errorCode":null,"errorMessage":"Localhost label target is not an allowed workspace port.","messagePattern":"Localhost label target is not an allowed workspace port\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ipc/localhost-worktree-labels.ts","lineNumber":68,"sourceCode":"  const matches = scan.ports.some((port) => {\n    if (String(port.port) !== targetPort) {\n      return false\n    }\n    if (normalizeLocalhostHostname(port.connectHost) === targetHost) {\n      return true\n    }\n    const advertisedUrl = 'advertisedUrl' in port ? port.advertisedUrl : undefined\n    if (!advertisedUrl) {\n      return false\n    }\n    try {\n      return normalizeLocalhostHostname(new URL(advertisedUrl).hostname) === targetHost\n    } catch {\n      return false\n    }\n  })\n  if (!matches) {\n    throw new Error('Localhost label target is not an allowed workspace port.')\n  }\n}\n\nfunction parseRegisterArgs(value: unknown): LocalhostWorktreeLabelRoute {\n  if (!value || typeof value !== 'object') {\n    throw new Error('Invalid localhost label route.')\n  }\n  const candidate = value as Record<string, unknown>\n  const targetUrl = readRequiredString(candidate.targetUrl, 'targetUrl')\n  const projectName = readRequiredString(candidate.projectName, 'projectName')\n  const worktreeName = readRequiredString(candidate.worktreeName, 'worktreeName')\n  return {\n    targetUrl,\n    projectName,\n    worktreeName,\n    repoId: readOptionalString(candidate.repoId),\n    worktreeId: readOptionalString(candidate.worktreeId)\n  }","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/localhost-worktree-labels.ts#L50-L86","documentation":"Thrown by assertAllowedTarget after the URL parses but the target host is not a loopback host AND no workspace port probe's advertisedUrl hostname matches the target host. This is the SSRF allowlist enforcement: only loopback hosts or hosts advertised by discovered workspace port probes are permitted as proxy targets.","triggerScenarios":"Registering a localhost label route whose targetUrl host is not in LOOPBACK_LOCALHOST_HOSTS and is not the hostname of any advertisedUrl in the scanned workspace port probes. E.g. targeting an external LAN/internet host, or a loopback variant not in the loopback set, or a port whose probe was metadata-skipped (dropping advertisedUrl per #11161).","commonSituations":"The target service has not yet been probed/registered as a workspace port. The advertisedUrl differs in hostname from the target (e.g. 127.0.0.1 vs localhost). A metadata-skip dropped the probe so the allowlist is narrower than expected. The user points at an external host which is intentionally blocked.","solutions":["Target a host in the loopback set (e.g. localhost, 127.0.0.1) for local services.","Ensure the workspace port probe for the target service has run and advertises a URL whose hostname matches your target.","If the probe was metadata-skipped (#11161), trigger a re-scan so advertisedUrl is populated.","Do not attempt to proxy to external/LAN hosts; the allowlist intentionally blocks them."],"exampleFix":"// before\nawait ipc.call('localhostLabel:register', { targetUrl: 'http://my-lan-host:3000', ... })\n\n// after\nawait ipc.call('localhostLabel:register', { targetUrl: 'http://127.0.0.1:3000', ... })","handlingStrategy":"validation","validationCode":"const host = normalizeLocalhostHostname(new URL(targetUrl).hostname)\nif (!LOOPBACK_LOCALHOST_HOSTS.has(host)) {\n  const probes = await scanWorkspacePortProbes(...)\n  const ok = probes.some(p => 'advertisedUrl' in p && normalizeLocalhostHostname(new URL(p.advertisedUrl).hostname) === host)\n  if (!ok) throw new Error('target not an allowed workspace port')\n}","typeGuard":"function isLoopbackHost(host: string, loopbackSet: Set<string>): boolean {\n  return loopbackSet.has(host)\n}","tryCatchPattern":null,"preventionTips":["Prefer loopback hosts (localhost/127.0.0.1) for local service targets.","Ensure the workspace port probe has run and advertises a matching URL.","Trigger a re-scan if a probe was metadata-skipped (#11161)."],"tags":["security","ssrf","allowlist","localhost","port-probe","ipc"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}