abhigyanpatwari/GitNexus · error

Invalid URL

Error message

Invalid URL

What it means

validateGitUrl performs SSRF-safe validation of git URLs. First it requires the string to be parseable by the URL constructor; anything malformed throws 'Invalid URL'. The guard only accepts http(s) git URLs, so unparseable input is rejected before any protocol checks.

Source

Thrown at gitnexus/src/core/net/url-guard.ts:21

// 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 an outbound http(s) URL to prevent SSRF.
 * 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');
  }

  if (parsed.search || parsed.hash) {
    throw new Error('Git URLs must not include query strings or fragments');
  }

  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)

View on GitHub (pinned to 0d1aed942f)

Solutions

  1. Convert scp-style remotes to https form: git@github.com:acme/api.git → https://github.com/acme/api.git.
  2. Include the scheme explicitly: prefix the value with https:// if it is missing.
  3. Trim whitespace and re-check the URL in your browser/with `new URL()` before passing it in.
  4. Use a local filesystem path API instead of cloneOrPull if you intend to clone from a local directory.

Example fix

// before
await cloneOrPull('git@github.com:acme/api.git', dest);

// after
await cloneOrPull('https://github.com/acme/api.git', dest);
Defensive patterns

Strategy: validation

Validate before calling

function looksLikeHttpUrl(u: string): boolean {
  try { const p = new URL(u); return p.protocol === 'https:' || p.protocol === 'http:'; }
  catch { return false; }
}

Type guard

const isParsableUrl = (u: string): boolean => { try { new URL(u); return true; } catch { return false; } };

Try / catch

try {
  validateGitUrl(url);
} catch (err) {
  if (err instanceof Error && err.message === 'Invalid URL') {
    throw new Error(`not a valid URL: ${url} — include scheme, e.g. https://host/repo.git`);
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling validateGitUrl (directly or via cloneOrPull / normalizedRegistry / sanitizedHttpUrl) with a string that new URL() cannot parse — missing scheme, spaces, scp-like syntax git@host:path, or bare hostnames.

Common situations: Passing a classic scp-style git remote (git@github.com:acme/api.git) which URL() treats as invalid; a typo like 'httpsgithub.com/acme' or missing '://'; copying a repo path instead of a URL; config containing a relative local path.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@0d1aed942f (2026-09-08). Data as JSON: /api/errors/0502e1016eee0682. Report an issue: GitHub.