ruvnet/ruflo · warning · Error
Invalid git ref: too long
Error message
Invalid git ref: too long
What it means
Thrown by validateGitRef when ref.length > 256. Git refs are bounded in practice (git itself enforces no hard limit but refs longer than a few hundred chars are always pathological), so this guard caps the input to block memory/cpu abuse and malformed inputs. This is the third and final validation check, after character-class and '..' checks.
Source
Thrown at v3/@claude-flow/cli/src/ruvector/diff-classifier.ts:383
/**
* Validate git ref to prevent command injection
* Only allows safe characters: alphanumeric, -, _, /, ., ~, ^
*/
function validateGitRef(ref: string): void {
// Block shell metacharacters and dangerous patterns
if (!/^[a-zA-Z0-9_\-./~^@]+$/.test(ref)) {
throw new Error(`Invalid git ref: contains unsafe characters`);
}
// Block multiple dots (path traversal)
if (ref.includes('..') && !ref.match(/^[a-zA-Z0-9_\-]+\.\.\.?[a-zA-Z0-9_\-]+$/)) {
if (!/^\w+\.\.[.\w]+$/.test(ref)) {
throw new Error(`Invalid git ref: suspicious pattern`);
}
}
// Max length check
if (ref.length > 256) {
throw new Error(`Invalid git ref: too long`);
}
}
/**
* Get git diff statistics using SINGLE combined command (optimized)
* Replaces two separate git commands with one
*/
export function getGitDiffNumstat(ref: string = 'HEAD'): DiffFile[] {
// SECURITY: Validate git ref to prevent command injection
validateGitRef(ref);
// Check cache first
const cacheKey = `numstat:${ref}`;
const cached = diffCache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
return cached.files;
}
View on GitHub (pinned to 6b01dc5a68)
Solutions
- Enforce a length cap at the application boundary (e.g. truncate or reject refs > 200 chars) before calling getGitDiffNumstat.
- If you genuinely need long refs, you can't bypass this guard — refactor to a shorter alias (git update-ref).
- Treat a >256 char ref as a bug in the upstream caller, not a legitimate input.
Example fix
// before
const files = getGitDiffNumstat(veryLongRef);
// after — bound the length at the call site
if (ref.length > 256) throw new Error(`ref too long (${ref.length}); expected < 256`);
const files = getGitDiffNumstat(ref); Defensive patterns
Strategy: validation
Validate before calling
function boundedGitRef(ref: unknown): string {
const s = String(ref ?? 'HEAD');
if (s.length > 200) throw new Error(`ref too long (${s.length}); expected < 200 chars`);
return s;
}
const files = getGitDiffNumstat(boundedGitRef(req.query.ref)); Type guard
function isLengthBoundedRef(ref: string, max = 256): boolean {
return typeof ref === 'string' && ref.length <= max;
} Try / catch
try {
return getGitDiffNumstat(ref);
} catch (e) {
if (/too long/.test(String(e))) {
throw new Error(`ref length ${String(ref).length} exceeds limit; input is pathological`);
}
throw e;
} Prevention
- Cap ref length at the application boundary (200 chars is generous — real refs are <100).
- Treat >256 char inputs as bugs or abuse, never as legitimate refs.
- Validate before calling getGitDiffNumstat so the error message is actionable.
When it happens
Trigger: A ref string built by concatenating many segments without bound; a ref read from a file/blob that wasn't truncated; a malformed input that's actually a git object ID with extra padding; an attacker probing with very long inputs (the validator is called on every diff).
Common situations: Tool reads a ref from a URL query string with no length cap; ref comes from unbounded user input in a dashboard; a bug concatenates the same ref repeatedly into one string.
Related errors
- Invalid git ref: contains unsafe characters
- Invalid git ref: suspicious pattern
- VALIDATION_ERROR
- candidate ${label} must ingest at least one vector
- records must be a non-empty array of {id?, vector, text?}
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/f4fc230f7c341964.
Report an issue: GitHub.