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
- Expose the git server over a real (public, https) hostname and use that URL
- For repos already on the server's machine, use the analyze-by-'path' option (absolute filesystem path) instead of cloning
- 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
- Never submit localhost or metadata hostnames in analyze URLs
- Model these as permanent 4xx-style rejections in retry policies — retrying cannot help
- Route local repos through the path option
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
- Sending a git credential over cleartext http:// (${u.host})
- ${source} entry "${trimmed}" must be an identifier or member
- Refusing to start eval-server on non-loopback host ${host} w
- ${TRUSTED_CACHE_DIRECTORY_ENV} must not traverse symbolic li
- argument contains NUL/CR/LF, unsafe for the Windows shell: $
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/ba33390dd8b8784f.
Report an issue: GitHub.