{"record":{"id":"f4fc230f7c341964","repo":"ruvnet/ruflo","slug":"invalid-git-ref-too-long","errorCode":null,"errorMessage":"Invalid git ref: too long","messagePattern":"Invalid git ref: too long","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"v3/@claude-flow/cli/src/ruvector/diff-classifier.ts","lineNumber":383,"sourceCode":"\n/**\n * Validate git ref to prevent command injection\n * Only allows safe characters: alphanumeric, -, _, /, ., ~, ^\n */\nfunction validateGitRef(ref: string): void {\n  // Block shell metacharacters and dangerous patterns\n  if (!/^[a-zA-Z0-9_\\-./~^@]+$/.test(ref)) {\n    throw new Error(`Invalid git ref: contains unsafe characters`);\n  }\n  // Block multiple dots (path traversal)\n  if (ref.includes('..') && !ref.match(/^[a-zA-Z0-9_\\-]+\\.\\.\\.?[a-zA-Z0-9_\\-]+$/)) {\n    if (!/^\\w+\\.\\.[.\\w]+$/.test(ref)) {\n      throw new Error(`Invalid git ref: suspicious pattern`);\n    }\n  }\n  // Max length check\n  if (ref.length > 256) {\n    throw new Error(`Invalid git ref: too long`);\n  }\n}\n\n/**\n * Get git diff statistics using SINGLE combined command (optimized)\n * Replaces two separate git commands with one\n */\nexport function getGitDiffNumstat(ref: string = 'HEAD'): DiffFile[] {\n  // SECURITY: Validate git ref to prevent command injection\n  validateGitRef(ref);\n\n  // Check cache first\n  const cacheKey = `numstat:${ref}`;\n  const cached = diffCache.get(cacheKey);\n  if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {\n    return cached.files;\n  }\n","sourceCodeStart":365,"sourceCodeEnd":401,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/cli/src/ruvector/diff-classifier.ts#L365-L401","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nconst files = getGitDiffNumstat(veryLongRef);\n\n// after — bound the length at the call site\nif (ref.length > 256) throw new Error(`ref too long (${ref.length}); expected < 256`);\nconst files = getGitDiffNumstat(ref);","handlingStrategy":"validation","validationCode":"function boundedGitRef(ref: unknown): string {\n  const s = String(ref ?? 'HEAD');\n  if (s.length > 200) throw new Error(`ref too long (${s.length}); expected < 200 chars`);\n  return s;\n}\n\nconst files = getGitDiffNumstat(boundedGitRef(req.query.ref));","typeGuard":"function isLengthBoundedRef(ref: string, max = 256): boolean {\n  return typeof ref === 'string' && ref.length <= max;\n}","tryCatchPattern":"try {\n  return getGitDiffNumstat(ref);\n} catch (e) {\n  if (/too long/.test(String(e))) {\n    throw new Error(`ref length ${String(ref).length} exceeds limit; input is pathological`);\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["git","input-validation","dos-prevention"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}