abhigyanpatwari/GitNexus · error · Error

Cloning from private/internal addresses is not allowed

Error message

Cloning from private/internal addresses is not allowed

What it means

validateGitUrl lowercases the parsed hostname and rejects a fixed blocklist — localhost, metadata.google.internal, metadata.azure.com, metadata.internal — before DNS or clone happens. These are the hostnames of the server itself and of cloud instance-metadata services; cloning from them is the canonical SSRF primitive this guard exists to deny.

Source

Thrown at gitnexus/src/server/git-clone.ts:94

 * IPv6 private ranges, cloud metadata hostnames, and numeric IP encodings.
 */
export function validateGitUrl(url: string): void {
  let parsed: URL;
  try {
    parsed = new URL(url);
  } catch {
    throw new Error('Invalid URL');
  }

  if (!['https:', 'http:'].includes(parsed.protocol)) {
    throw new Error('Only https:// and http:// git URLs are allowed');
  }

  const host = parsed.hostname.toLowerCase();

  // Block known dangerous hostnames (cloud metadata services)
  if (BLOCKED_HOSTNAMES.has(host)) {
    throw new Error('Cloning from private/internal addresses is not allowed');
  }

  // Strip IPv6 brackets if present (URL parser behavior varies across Node versions)
  let normalizedHost = host;
  if (host.startsWith('[') && host.endsWith(']')) {
    normalizedHost = host.slice(1, -1);
  }

  // Check if this is an IPv6 address
  // Use manual colon detection as fallback since isIP may return 0 for some
  // normalized IPv6 forms (e.g. ::ffff:7f00:1)
  const isIPv6 = isIP(normalizedHost) === 6 || normalizedHost.includes(':');
  if (isIPv6) {
    assertNotPrivateIPv6(normalizedHost);
    return;
  }

  // Check if this is an IPv4 address (including numeric encodings)

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Expose the git server over a real (public, https) hostname and use that URL
  2. For repos already on the server's machine, use the analyze-by-'path' option (absolute filesystem path) instead of cloning
  3. Never attempt to reach cloud metadata endpoints through this API

Example fix

// before
{ url: 'http://localhost:8080/myrepo.git' }

// after
{ path: '/srv/git/myrepo' } // analyze the local copy directly
Defensive patterns

Strategy: validation

Validate before calling

const BLOCKED = new Set(['localhost', 'metadata.google.internal', 'metadata.azure.com', 'metadata.internal']);
function targetsBlockedHost(url) {
  try { return BLOCKED.has(new URL(url).hostname.toLowerCase()); } catch { return true; }
}

Type guard

function isNonBlockedHostname(host) { return !BLOCKED.has(String(host).toLowerCase()); }

Try / catch

try { validateGitUrl(url); }
catch (e) {
  if (/private\/internal addresses|Invalid URL|https/.test(e.message)) rejectSubmission(e.message); // permanent client error; do not retry
  else throw e;
}

Prevention

When it happens

Trigger: POST /api/analyze with url='http://localhost:8080/repo.git' (local Gitea on the same box) or 'http://metadata.google.internal/computeMetadata/v1/...' (probing GCP metadata via the clone feature).

Common situations: Testing against a self-hosted local git server; penetration-test payloads; misconfigured tooling that records 'localhost' instead of a real hostname for an internal mirror. The block is intentional, not a bug to work around from untrusted input.

Related errors


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