{"record":{"id":"195ecd5b36d078f5","repo":"stablyai/orca","slug":"access-denied-invalid-git-file-path","errorCode":null,"errorMessage":"Access denied: invalid git file path","messagePattern":"Access denied: invalid git file path","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ipc/filesystem-auth.ts","lineNumber":532,"sourceCode":"    }\n  }\n  return bestRoot\n}\n\nasync function normalizeExistingPath(resolvedPath: string): Promise<string> {\n  try {\n    return resolve(await realpath(resolvedPath))\n  } catch (error) {\n    if (isENOENT(error)) {\n      return resolvedPath\n    }\n    throw error\n  }\n}\n\nexport function validateGitRelativeFilePath(worktreePath: string, filePath: string): string {\n  if (!filePath || filePath.includes('\\0') || resolve(filePath) === filePath) {\n    throw new Error('Access denied: invalid git file path')\n  }\n\n  const resolvedFilePath = resolve(worktreePath, filePath)\n  if (!isDescendantOrEqual(resolvedFilePath, worktreePath)) {\n    throw new Error('Access denied: git file path escapes the selected worktree')\n  }\n\n  const normalizedRelativePath = relative(worktreePath, resolvedFilePath)\n  if (!normalizedRelativePath) {\n    throw new Error('Access denied: invalid git file path')\n  }\n\n  return normalizedRelativePath\n}\n","sourceCodeStart":514,"sourceCodeEnd":547,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/filesystem-auth.ts#L514-L547","documentation":"First validation gate in `validateGitRelativeFilePath`: rejects a `filePath` that is empty, contains a NUL byte, or is already absolute (`resolve(filePath) === filePath` means joining it onto the worktree would be a no-op and the path escapes). This is the input-shape check before any containment comparison.","triggerScenarios":"Calling `validateGitRelativeFilePath(worktreePath, filePath)` with `filePath` being `''`, containing `\\0`, or an absolute path such as `/etc/passwd` or `C:\\Windows\\system32`.","commonSituations":"Renderer forwarded an absolute path where a git-relative path was expected; empty file field from an unselected diff; NUL byte from malformed input; Windows drive-absolute path passed on a POSIX host or vice versa.","solutions":["Pass a strictly relative path (e.g. `src/foo.ts`) derived from `git diff --name-only` or equivalent.","Reject empty/NUL-containing paths at the renderer before invoking the IPC handler.","Strip leading slashes / drive letters so the path is relative before calling."],"exampleFix":"// before\nvalidateGitRelativeFilePath(worktreePath, '/etc/passwd')\n\n// after\nvalidateGitRelativeFilePath(worktreePath, 'src/main/ipc/diagnostics.ts')","handlingStrategy":"validation","validationCode":"// Only pass strictly relative, non-empty, NUL-free paths to validateGitRelativeFilePath.\nfunction assertRelativeFilePath(p: unknown): asserts p is string {\n  if (typeof p !== 'string' || p.length === 0 || p.includes('\\0') || isAbsolute(p)) {\n    throw new Error('filePath must be a non-empty relative path with no NUL bytes')\n  }\n}\nassertRelativeFilePath(filePath)\nreturn validateGitRelativeFilePath(worktreePath, filePath)","typeGuard":"function isRelativeFilePath(p: unknown): p is string {\n  return typeof p === 'string' && p.length > 0 && !p.includes('\\0') && !isAbsolute(p)\n}","tryCatchPattern":"try {\n  return validateGitRelativeFilePath(worktreePath, filePath)\n} catch (e) {\n  if (e instanceof Error && e.message === 'Access denied: invalid git file path') {\n    // absolute/empty/NUL input; fix the source so only git-relative paths are sent\n    throw new InvalidGitPathError(e.message)\n  }\n  throw e\n}","preventionTips":["Derive file paths from `git diff --name-only` output so they are always git-relative.","Strip leading slashes and drive letters before passing a path to the validator.","Reject empty or NUL-containing paths at the renderer boundary."],"tags":["filesystem","security-boundary","input-validation","git","path-traversal","null-byte"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}