{"record":{"id":"17604dc3d3da10f3","repo":"ruvnet/ruflo","slug":"refusing-to-probe-non-loopback-meta-proxy-bind","errorCode":null,"errorMessage":"Refusing to probe non-loopback Meta-Proxy bind \"${bind}\".","messagePattern":"Refusing to probe non-loopback Meta-Proxy bind \"(.+?)\"\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/proxy/activation.ts","lineNumber":33,"sourceCode":"} from './paths.js';\n\nexport interface EffectiveProxy { version: string; pid: number; executable: string; }\ntype Wait = (milliseconds: number) => Promise<void>;\nconst waitNormally: Wait = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));\n\nfunction processExists(pid: number): boolean {\n  try { process.kill(pid, 0); return true; } catch (error) {\n    return (error as NodeJS.ErrnoException).code === 'EPERM';\n  }\n}\n\nfunction effectiveEndpoint(): string {\n  let bind = '127.0.0.1:11435';\n  try {\n    const match = fs.readFileSync(proxyConfigPath(), 'utf8').match(/^bind\\s*=\\s*\"([^\"]+)\"\\s*$/m);\n    if (match?.[1]) bind = match[1];\n  } catch { /* documented default */ }\n  if (!isLoopbackBind(bind)) throw new Error(`Refusing to probe non-loopback Meta-Proxy bind \"${bind}\".`);\n  return `http://${bind}`;\n}\n\nfunction executableFor(pid: number, platform: NodeJS.Platform): string | null {\n  try {\n    if (platform === 'linux') {\n      const result = spawnSync('readlink', ['-f', `/proc/${pid}/exe`], { encoding: 'utf8', timeout: 2_000 });\n      return result.status === 0 ? result.stdout.trim() || null : null;\n    }\n    if (platform === 'win32') {\n      const command = `$p = Get-CimInstance Win32_Process -Filter 'ProcessId = ${pid}'; if ($null -ne $p) { [Console]::Out.Write($p.ExecutablePath) }`;\n      const result = spawnSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', command], { encoding: 'utf8', timeout: 2_000, windowsHide: true });\n      return result.status === 0 ? result.stdout.trim() || null : null;\n    }\n    const result = spawnSync('ps', ['-p', String(pid), '-o', 'comm='], { encoding: 'utf8', timeout: 2_000 });\n    return result.status === 0 ? result.stdout.trim() || null : null;\n  } catch { return null; }\n}","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/ruvnet/ruflo/blob/29f048fc3b556f857cf2b126d2a84c19d2daa0d0/v3/@claude-flow/cli/src/proxy/activation.ts#L15-L51","documentation":"effectiveEndpoint() reads the Meta-Proxy config file's `bind` value (defaulting to 127.0.0.1:11435) before probing the daemon. If the configured bind address is not a loopback address, the library refuses to probe it, because probing (and later signaling) a proxy listening on a non-loopback interface could affect other machines' daemons. This is a deliberate safety guard in the library, not a network failure.","triggerScenarios":"Calling any function that resolves the effective endpoint (probeEffectiveProxy, installAndActivateProxy via stopEffective/launchAndVerify) while proxyConfigPath()'s config contains a `bind = \"...\"` line whose value is not loopback (e.g. \"0.0.0.0:11435\", \"192.168.1.10:11435\", a hostname, or a non-loopback IP).","commonSituations":"Users edit the Meta-Proxy config to expose the proxy on a LAN address or all interfaces so other hosts/containers can reach it; Docker/Kubernetes setups binding 0.0.0.0; copy-pasted config from a remote-server guide; a stale config left by a manual daemon setup.","solutions":["Edit the Meta-Proxy config file (see proxyConfigPath(), typically under ~/.metaharness) and set bind to a loopback address, e.g. bind = \"127.0.0.1:11435\"","If you intentionally need a non-loopback bind, run/probe the daemon yourself outside this library's activation flow; the CLI will not probe non-loopback endpoints by design","Remove the bind line entirely to fall back to the documented default 127.0.0.1:11435","Verify the parsed value is loopback before activating: node -e \"console.log(require('net').isLoopback?.(...) )\" or check the address manually"],"exampleFix":"// before (proxy config)\nbind = \"0.0.0.0:11435\"\n// after\nbind = \"127.0.0.1:11435\"","handlingStrategy":"validation","validationCode":"import fs from 'node:fs';\n// Read the same bind the library will use and reject non-loopback before calling.\nconst cfg = fs.readFileSync(proxyConfigPath(), 'utf8');\nconst bind = cfg.match(/^bind\\s*=\\s*\"([^\"]+)\"\\s*$/m)?.[1] ?? '127.0.0.1:11435';\nconst host = bind.split(':')[0];\nif (!(host === 'localhost' || host === '127.0.0.1' || host === '::1' || host === '[::1]')) {\n  throw new Error(`Fix bind in proxy config first: \"${bind}\" is not loopback`);\n}\nawait installAndActivateProxy(version);","typeGuard":"function isLoopbackBind(bind: string): boolean {\n  const host = bind.replace(/^\\[|\\]$/g, '').split(':')[0];\n  return host === 'localhost' || host === '127.0.0.1' || host === '::1' || host.endsWith('.127.0.0.1') || /^127\\./.test(host);\n}","tryCatchPattern":"null","preventionTips":["Keep bind on 127.0.0.1:11435 unless you deliberately manage remote access yourself","Lint/validate the proxy config in CI before running proxy activation","Never copy server-oriented configs (0.0.0.0 binds) into your local Meta-Harness config","If you need remote reach, front the loopback proxy with your own reverse proxy"],"tags":["config","security","loopback","proxy"],"backgroundTag":"non-loopback-bind-refused","analyzedSha":"29f048fc3b556f857cf2b126d2a84c19d2daa0d0","analyzedAt":"2026-09-01T11:37:30.251Z","contentChangedAt":"2026-09-01T11:37:30.251Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}