{"record":{"id":"c767543ff3fb90af","repo":"abhigyanpatwari/GitNexus","slug":"local-path-must-be-normalized-and-must-not-contain","errorCode":null,"errorMessage":"local_path must be normalized and must not contain traversal segments","messagePattern":"local_path must be normalized and must not contain traversal segments","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/auto-sync/path-security.ts","lineNumber":110,"sourceCode":"  );\n  assertNotDangerousRoot(realRoot);\n  assertNotGitNexusInternalRoot(realRoot);\n  const quarantineRoot = path.join(getAutoSyncWatchDir(), 'quarantine');\n  await pruneQuarantineEntries(quarantineRoot);\n\n  return {\n    root: realRoot,\n    quarantineRoot,\n    quarantineRetentionDays: QUARANTINE_RETENTION_DAYS,\n  };\n}\n\nexport function normalizeConfiguredCloneRoot(localPath: string): string {\n  const value = localPath.trim();\n  if (!value) throw new Error('local_path is required');\n  if (!path.isAbsolute(value)) throw new Error('local_path must be an absolute path');\n  if (value.split(path.sep).includes('..')) {\n    throw new Error('local_path must be normalized and must not contain traversal segments');\n  }\n  const resolved = path.resolve(value);\n  if (resolved !== path.normalize(value)) {\n    throw new Error('local_path must be normalized and must not contain traversal segments');\n  }\n  return resolved;\n}\n\nexport async function quarantineAutoSyncPartial(\n  targetDir: string,\n  quarantineRoot: string,\n): Promise<string> {\n  await fs.mkdir(quarantineRoot, { recursive: true, mode: 0o700 });\n  const base = path.basename(targetDir);\n  const stamp = new Date().toISOString().replace(/[:.]/g, '-');\n  const destination = path.join(\n    quarantineRoot,\n    `auto-sync-${stamp}-${process.pid}-${randomUUID()}-${base}`,","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/0d1aed942f0e8b5d3bac27519fff441aceea722d/gitnexus/src/core/auto-sync/path-security.ts#L92-L128","documentation":"normalizeConfiguredCloneRoot rejects local_path values containing a \"..\" segment, refusing path traversal before resolution. Splitting the raw value on the platform separator and looking for \"..\" catches traversal attempts regardless of whether resolution would collapse them.","triggerScenarios":"parseAutoSyncConfig receives a local_path with a \"..\" path segment, e.g. \"/home/user/../etc/repos\" or \"/srv/clones/../../etc\".","commonSituations":"Config values built by concatenation with user input, security-scanning tools flagging traversal-capable paths, or hand-written paths with redundant parent steps.","solutions":["Remove the \"..\" segments and write the direct absolute path to the clone root.","If the value is assembled from parts, join and clean it in code before assigning local_path.","Re-run parseAutoSyncConfig to confirm the normalized path is accepted."],"exampleFix":"// before (config)\nlocal_path: \"/home/user/../srv/clones\"\n// after (config)\nlocal_path: \"/srv/clones\"","handlingStrategy":"validation","validationCode":"if (localPath.split(path.sep).includes('..')) throw new Error('local_path must not contain traversal (\"..\") segments');","typeGuard":null,"tryCatchPattern":"try {\n  parseAutoSyncConfig(raw);\n} catch (err) {\n  if (err.message.includes('must be normalized and must not contain traversal')) {\n    console.error('Rewrite local_path as a direct absolute path without \"..\" segments.');\n  } else throw err;\n}","preventionTips":["Never build local_path from untrusted/user-supplied segments.","Normalize joined paths in code before persisting them to config.","Treat \"..\" in configured paths as a security smell and reject it in review/CI."],"tags":["config","path","security","path-traversal","auto-sync"],"backgroundTag":"path-traversal-blocked","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"}