stablyai/orca · error · Error

Localhost label target is not an allowed workspace port.

Error message

Localhost label target is not an allowed workspace port.

What it means

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.

Source

Thrown at src/main/ipc/localhost-worktree-labels.ts:68

  const matches = scan.ports.some((port) => {
    if (String(port.port) !== targetPort) {
      return false
    }
    if (normalizeLocalhostHostname(port.connectHost) === targetHost) {
      return true
    }
    const advertisedUrl = 'advertisedUrl' in port ? port.advertisedUrl : undefined
    if (!advertisedUrl) {
      return false
    }
    try {
      return normalizeLocalhostHostname(new URL(advertisedUrl).hostname) === targetHost
    } catch {
      return false
    }
  })
  if (!matches) {
    throw new Error('Localhost label target is not an allowed workspace port.')
  }
}

function parseRegisterArgs(value: unknown): LocalhostWorktreeLabelRoute {
  if (!value || typeof value !== 'object') {
    throw new Error('Invalid localhost label route.')
  }
  const candidate = value as Record<string, unknown>
  const targetUrl = readRequiredString(candidate.targetUrl, 'targetUrl')
  const projectName = readRequiredString(candidate.projectName, 'projectName')
  const worktreeName = readRequiredString(candidate.worktreeName, 'worktreeName')
  return {
    targetUrl,
    projectName,
    worktreeName,
    repoId: readOptionalString(candidate.repoId),
    worktreeId: readOptionalString(candidate.worktreeId)
  }

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Target a host in the loopback set (e.g. localhost, 127.0.0.1) for local services.
  2. Ensure the workspace port probe for the target service has run and advertises a URL whose hostname matches your target.
  3. If the probe was metadata-skipped (#11161), trigger a re-scan so advertisedUrl is populated.
  4. Do not attempt to proxy to external/LAN hosts; the allowlist intentionally blocks them.

Example fix

// before
await ipc.call('localhostLabel:register', { targetUrl: 'http://my-lan-host:3000', ... })

// after
await ipc.call('localhostLabel:register', { targetUrl: 'http://127.0.0.1:3000', ... })
Defensive patterns

Strategy: validation

Validate before calling

const host = normalizeLocalhostHostname(new URL(targetUrl).hostname)
if (!LOOPBACK_LOCALHOST_HOSTS.has(host)) {
  const probes = await scanWorkspacePortProbes(...)
  const ok = probes.some(p => 'advertisedUrl' in p && normalizeLocalhostHostname(new URL(p.advertisedUrl).hostname) === host)
  if (!ok) throw new Error('target not an allowed workspace port')
}

Type guard

function isLoopbackHost(host: string, loopbackSet: Set<string>): boolean {
  return loopbackSet.has(host)
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/68626cfc52ac8291. Report an issue: GitHub.