abhigyanpatwari/GitNexus · critical · Error

Refusing to start eval-server on non-loopback host ${host} w

Error message

Refusing to start eval-server on non-loopback host ${host} without authentication. Set GITNEXUS_AUTH_TOKEN or bind to 127.0.0.1, localhost, or ::1.

What it means

The eval-server query surface exposes tool results (query/context/impact/detect_changes) that can read the knowledge graph; binding it to a non-loopback host without a bearer token would expose that surface to anything on the network. `assertSecureEvalServerBinding` refuses to start in that posture. Loopback hosts (127.x, ::1, localhost) are exempt.

Source

Thrown at gitnexus/src/cli/eval-server.ts:155

  host: string,
  env: NodeJS.ProcessEnv,
  cwd: string = process.cwd(),
): { token?: string; warning?: string } {
  try {
    return { token: resolveEvalServerAuthToken(env, cwd) };
  } catch (error) {
    if (isEvalServerLoopbackHost(host)) {
      const reason = error instanceof Error ? error.message : String(error);
      return { warning: `${reason} Continuing without authentication on loopback host ${host}.` };
    }
    throw error;
  }
}

/** Refuse exposure of the eval-server query surface without authentication. */
export function assertSecureEvalServerBinding(host: string, authToken: string | undefined): void {
  if (!authToken && !isEvalServerLoopbackHost(host)) {
    throw new Error(
      `Refusing to start eval-server on non-loopback host ${host} without authentication. ` +
        'Set GITNEXUS_AUTH_TOKEN or bind to 127.0.0.1, localhost, or ::1.',
    );
  }
}

/** Validate the exact Bearer header while keeping token comparison constant-time. */
export function isEvalServerBearerAuthorized(
  authorization: string | string[] | undefined,
  authToken: string | undefined,
): boolean {
  if (!authToken) return true;

  const expected = Buffer.from(`Bearer ${authToken}`, 'utf8');
  const supplied = typeof authorization === 'string' ? Buffer.from(authorization, 'utf8') : null;
  const sameLength = supplied?.length === expected.length;
  const candidate = sameLength && supplied ? supplied : Buffer.alloc(expected.length);
  return crypto.timingSafeEqual(candidate, expected) && sameLength;

View on GitHub (pinned to d540b00184)

Solutions

  1. Set GITNEXUS_AUTH_TOKEN in the shell environment or in `.env`/`.env.local`.
  2. Bind to a loopback host instead: `--host 127.0.0.1`, `--host localhost`, or `--host ::1`.
  3. Ensure the host string resolves to a loopback address before the assertion runs.

Example fix

# before
gitnexus eval-server --host 0.0.0.0
# after
GITNEXUS_AUTH_TOKEN="$TOKEN" gitnexus eval-server --host 0.0.0.0
Defensive patterns

Strategy: validation

Validate before calling

import { assertSecureEvalServerBinding, isEvalServerLoopbackHost } from './eval-server.js';
// Resolve the token early so the failure is clear
const token = resolveEvalServerAuthToken(process.env);
if (!isEvalServerLoopbackHost(host)) {
  if (!token) throw new Error('GITNEXUS_AUTH_TOKEN required for non-loopback bind');
}
assertSecureEvalServerBinding(host, token);

Type guard

const isLoopbackHost = (h) =>
  h === 'localhost' || h === '::1' || (/^\d+\.\d+\.\d+\.\d+$/.test(h) && h.startsWith('127.'));

Prevention

When it happens

Trigger: Running `gitnexus eval-server --host 0.0.0.0` (or a LAN hostname) without GITNEXUS_AUTH_TOKEN set in the environment, `.env`, or `.env.local`.

Common situations: Running the eval-server inside Docker or a devbox with a container-facing bind address; CI that binds 0.0.0.0 for health checks; forgetting to provide the token in a non-loopback deployment.

Understand the failure class

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/b1f170fc4c752c30. Report an issue: GitHub.