abhigyanpatwari/GitNexus · error · Error
Could not extract a valid repository name from URL
Error message
Could not extract a valid repository name from URL
What it means
extractRepoName takes the last path segment of a git URL (via parseRepoNameFromUrl) and requires a filesystem-safe name matching ^[a-zA-Z0-9._-]+$, additionally rejecting '.', '..', and the 'unknown' sentinel. Anything else throws, because getCloneDir would otherwise let names like '..' or 'foo/bar' escape the clone root via path traversal.
Source
Thrown at gitnexus/src/server/git-clone.ts:50
export const REPO_NAME_PATTERN = /^[a-zA-Z0-9._-]+$/;
/**
* Extract the repository name from a git URL (HTTPS or SSH).
*
* Throws if the URL does not yield a filesystem-safe last segment. A name
* like `..` or `foo/bar` would otherwise let `getCloneDir(name)` escape the
* clone root via path traversal.
*/
export function extractRepoName(url: string): string {
const name = parseRepoNameFromUrl(url);
if (
!name ||
name === '.' ||
name === '..' ||
name === 'unknown' ||
!REPO_NAME_PATTERN.test(name)
) {
throw new Error('Could not extract a valid repository name from URL');
}
return name;
}
/** Get the clone target directory for a repo name. */
export function getCloneDir(repoName: string): string {
// Re-validate at the boundary even though extractRepoName already checked —
// callers may pass a repoName from another source (test fixtures, scripts).
if (!repoName || repoName === '.' || repoName === '..' || !REPO_NAME_PATTERN.test(repoName)) {
throw new Error('Invalid repository name');
}
return path.join(CLONE_ROOT, repoName);
}
// Cloud metadata hostnames that must never be reachable via user-supplied URLs
const BLOCKED_HOSTNAMES = new Set([
'localhost',
'metadata.google.internal',View on GitHub (pinned to aac7515d2a)
Solutions
- Send the canonical HTTPS URL ending in the repo slug, optionally with .git
- Ensure the repo slug is pure ASCII alphanumerics plus . _ - (rename or alias non-ASCII slugs)
- Trim whitespace and strip fragments/queries from user-pasted URLs before submitting
Example fix
// before const url = 'https://github.com/user/my repo'; extractRepoName(url); // throws // after const url = 'https://github.com/user/my-repo'; extractRepoName(url); // 'my-repo'
Defensive patterns
Strategy: validation
Validate before calling
const SAFE_NAME = /^[a-zA-Z0-9._-]+$/;
function lastSegment(url) { return new URL(url).pathname.replace(/\/+$/, '').split('/').pop() || ''; }
function urlYieldsSafeRepoName(url) {
try { const n = lastSegment(url).replace(/\.git$/, ''); return SAFE_NAME.test(n) && n !== '.' && n !== '..' && n !== 'unknown'; }
catch { return false; }
} Type guard
function isSafeRepoName(name) {
return typeof name === 'string' && name.length > 0 && name !== '.' && name !== '..' && name !== 'unknown' && /^[a-zA-Z0-9._-]+$/.test(name);
} Try / catch
try { targetPath = getCloneDir(extractRepoName(url)); }
catch (e) {
if (e.message === 'Could not extract a valid repository name from URL') throw new BadRequest(`unsupported repo url: ${url}`, 400);
throw e;
} Prevention
- Normalize URLs client-side: trim, strip fragments/queries, drop trailing slashes
- Reject or transliterate non-ASCII repo slugs before submission
- Keep repo names to [A-Za-z0-9._-] by policy
When it happens
Trigger: POST /api/analyze (or any cloneOrPull caller) with a URL whose final segment is empty ('https://github.com/user/') or contains characters outside the safe set — spaces ('my repo'), CJK/unicode, backslashes, or shell metacharacters ('repo;ls').
Common situations: Trailing-slash or bare-host URLs; repositories with human-display names containing spaces/unicode; pasted URLs with a trailing fragment or whitespace; URLs where the repo slug itself is non-ASCII.
Related errors
- Invalid URL
- Invalid repository name
- Only https:// and http:// git URLs are allowed
- ${source} entries must all be strings.
- ${source} entries must not be empty.
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/520285eb83c45f4c.
Report an issue: GitHub.