abhigyanpatwari/GitNexus · error · Error

Invalid URL

Error message

Invalid URL

What it means

validateGitUrl's first step parses the input with new URL(); any string the WHATWG URL parser rejects — missing scheme, embedded spaces/control characters, bare 'github.com/user/repo' — throws and is rethrown as 'Invalid URL'. This is the malformed-input gate in front of the SSRF checks that follow.

Source

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

// Cloud metadata hostnames that must never be reachable via user-supplied URLs
const BLOCKED_HOSTNAMES = new Set([
  'localhost',
  'metadata.google.internal',
  'metadata.azure.com',
  'metadata.internal',
]);

/**
 * Validate a git URL to prevent SSRF attacks.
 * Only allows https:// and http:// schemes. Blocks private/internal addresses,
 * 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);
  }

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Trim whitespace/newlines from the URL before submitting
  2. Prepend https:// when the scheme is missing
  3. Run new URL(url) client-side as a pre-flight check
  4. Convert scp-style git@host:repo remotes to https://host/repo form

Example fix

// before
const url = 'github.com/user/repo.git';
validateGitUrl(url); // Invalid URL

// after
const url = 'https://github.com/user/repo.git';
validateGitUrl(url); // ok
Defensive patterns

Strategy: validation

Validate before calling

function isParseableHttpUrl(s) {
  if (typeof s !== 'string') return false;
  try { const u = new URL(s.trim()); return u.protocol === 'https:' || u.protocol === 'http:'; }
  catch { return false; }
}

Type guard

function asTrimmedAbsoluteUrl(raw) {
  const s = typeof raw === 'string' ? raw.trim() : '';
  if (!s) return null;
  const withScheme = /^[a-z][a-z0-9+.-]*:/i.test(s) ? s : `https://${s}`;
  try { return new URL(withScheme).href; } catch { return null; }
}

Try / catch

try { validateGitUrl(url); }
catch (e) {
  if (e.message === 'Invalid URL') { const fixed = asTrimmedAbsoluteUrl(url); if (!fixed) throw e; validateGitUrl(fixed); }
  else throw e;
}

Prevention

When it happens

Trigger: POST /api/analyze with url lacking a scheme ('github.com/user/repo.git'), containing raw spaces or newlines ('https:// ex ample.com'), or otherwise unparseable garbage such as pasted placeholder text.

Common situations: Users omitting https:// because git itself tolerates it; copy-paste introducing whitespace or a newline; frontends not trimming the field; scp-style 'git@host:repo' syntax, which the URL parser cannot parse at all.

Related errors


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