{"record":{"id":"22257d9d6fe536c8","repo":"abhigyanpatwari/GitNexus","slug":"auto-sync-clone-root-is-owned-by-uid-stat-uid","errorCode":null,"errorMessage":"auto-sync clone root is owned by uid ${stat.uid}, not current process uid","messagePattern":"auto-sync clone root is owned by uid (.+?), not current process uid","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/auto-sync/path-security.ts","lineNumber":270,"sourceCode":"    }\n    if (stat.isSymbolicLink())\n      throw new Error(`Refusing symlink in auto-sync clone root path: ${current}`);\n  }\n}\n\nexport async function assertDirectoryOwnerAndPermissions(root: string): Promise<void> {\n  const stat = await fs.stat(root);\n  if (!stat.isDirectory()) throw new Error(`auto-sync clone root is not a directory: ${root}`);\n  // POSIX uid/mode have no meaning on Windows, and this runs on every tick for\n  // every project, so throwing here failed 100% of repos forever while `watch\n  // status` still read `running`. Skip the ownership assertions rather than the\n  // whole feature: the caller's other guards — dangerous-root rejection\n  // (including the Windows system roots), symlink refusal, realpath containment\n  // and the GitNexus-internal-root check — all still apply, and managed git runs\n  // with `core.hooksPath` pinned to the null device.\n  if (process.platform === 'win32') return;\n  if (typeof process.getuid === 'function' && stat.uid !== process.getuid()) {\n    throw new Error(`auto-sync clone root is owned by uid ${stat.uid}, not current process uid`);\n  }\n  const mode = stat.mode & 0o777;\n  const groupWritable = (mode & 0o020) !== 0;\n  const worldWritable = (mode & 0o002) !== 0;\n  if (worldWritable) {\n    throw new Error(`Refusing world-writable auto-sync clone root: ${root}`);\n  }\n  if (groupWritable) {\n    throw new Error(`Refusing group-writable auto-sync clone root: ${root}`);\n  }\n}\n\nfunction assertContainedOrSame(root: string, child: string, message: string): void {\n  const rel = path.relative(root, child);\n  if (rel.startsWith('..') || path.isAbsolute(rel)) throw new Error(message);\n}\n","sourceCodeStart":252,"sourceCodeEnd":287,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/0d1aed942f0e8b5d3bac27519fff441aceea722d/gitnexus/src/core/auto-sync/path-security.ts#L252-L287","documentation":"Thrown by assertDirectoryOwnerAndPermissions (POSIX only; skipped on Windows) when the clone root directory's st_uid differs from the current process uid. A root owned by another user could be modified by that user's processes, letting them inject content into repositories that auto-sync clones and indexes, so the guard refuses to trust it. This check runs on every watch tick, so the failure persists until ownership is fixed.","triggerScenarios":"Thrown at gitnexus/src/core/auto-sync/path-security.ts:270 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["chown the clone-root directory (and its contents) to the uid running the GitNexus watcher: sudo chown -R $(id -u):$(id -g) <root>","Recreate the directory as the watcher user if it was created by root or another account","Move the clone root to a directory under the watcher user's home or the GitNexus global dir, which the process owns"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"0d1aed942f0e8b5d3bac27519fff441aceea722d","analyzedAt":"2026-09-08T00:40:44.970Z","contentChangedAt":"2026-09-08T00:40:44.970Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}