{"record":{"id":"8d2611d5ad508bd9","repo":"abhigyanpatwari/GitNexus","slug":"repository-path-must-not-contain-a-nul-character","errorCode":null,"errorMessage":"Repository path must not contain a NUL character.","messagePattern":"Repository path must not contain a NUL character\\.","errorType":"validation","errorClass":"InvalidStoragePathError","httpStatus":null,"severity":"error","filePath":"gitnexus/src/storage/storage-resolver.ts","lineNumber":178,"sourceCode":"const isRepositoryLocalStoragePath = (repoPath: string, storagePath: string): boolean =>\n  samePath(comparablePath(defaultStoragePath(repoPath)), comparablePath(storagePath));\n\nconst isMissingFilesystemError = (error: unknown): boolean => {\n  const code = (error as NodeJS.ErrnoException)?.code;\n  return code === 'ENOENT' || code === 'ENOTDIR';\n};\n\nconst filesystemErrorDetail = (error: unknown): string => {\n  const code = (error as NodeJS.ErrnoException)?.code;\n  return code ? `${code}: ${(error as Error)?.message ?? String(error)}` : String(error);\n};\n\nconst resolveRepoPath = (value: string): string => {\n  if (typeof value !== 'string' || value.length === 0) {\n    throw new InvalidStoragePathError('Repository path must be non-empty.');\n  }\n  if (value.includes('\\0')) {\n    throw new InvalidStoragePathError('Repository path must not contain a NUL character.');\n  }\n  return path.resolve(value);\n};\n\nconst validateAbsolutePath = (value: string, label: string): string => {\n  if (typeof value !== 'string' || value.length === 0) {\n    throw new InvalidStoragePathError(`${label} must be an absolute, non-empty path.`);\n  }\n  if (value.includes('\\0')) {\n    throw new InvalidStoragePathError(`${label} must not contain a NUL character.`);\n  }\n  if (!path.isAbsolute(value)) {\n    throw new InvalidStoragePathError(`${label} must be an absolute path.`);\n  }\n  return path.resolve(value);\n};\n\n// Mirror registry lookup semantics without importing repo-manager and creating a cycle.","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/ac9a4e9abd8fd3058c070b72c23402a4f887929a/gitnexus/src/storage/storage-resolver.ts#L160-L196","documentation":"resolveRepoPath rejects repository paths containing a NUL byte ('\\0'), which POSIX/Windows filesystem APIs treat as a string terminator and which often signals path injection. The check runs before path.resolve so no filesystem access happens with the tainted value.","triggerScenarios":"Calling canonicalRepoPath/defaultStoragePath/resolvedRepoPath/requireDeletableStoragePath with a repo path string that embeds '\\0' — typically from untrusted input, binary-corrupted config, or buffer-to-string conversions of padded bytes.","commonSituations":"Reading a path from an untrusted file or request parameter that was never sanitized; decoding a UTF-16/UTF-32 buffer with wrong encoding leaving NUL padding; fuzzed or malicious CLI input.","solutions":["Strip or reject the offending input at the boundary: if (value.includes('\\0')) fail with your own clear error.","If the value came from a Buffer, decode with the correct encoding (buffer.toString('utf8')) and trim trailing NULs: value.replace(/\\0+$/, '').","Treat NUL-bearing input as hostile — log and reject rather than sanitize silently."],"exampleFix":"// before\nconst repoPath = rawBuffer.toString('utf16le'); // leaves NUL padding\nconst canonical = await canonicalRepoPath(repoPath);\n// after\nconst repoPath = rawBuffer.toString('utf16le').replace(/\\0+$/g, '');\nif (repoPath.includes('\\0')) throw new Error('repoPath contains NUL bytes');\nconst canonical = await canonicalRepoPath(repoPath);","handlingStrategy":"validation","validationCode":"if (typeof repoPath !== 'string' || repoPath.includes('\\0')) {\n  throw new Error('repoPath must be a string without NUL bytes');\n}","typeGuard":"const isSafePathString = (v: unknown): v is string => typeof v === 'string' && !v.includes('\\0');","tryCatchPattern":"try {\n  return await resolvedRepoPath(repoPath);\n} catch (e) {\n  if (e instanceof InvalidStoragePathError && e.message.includes('NUL')) {\n    throw new Error('repo path contained a NUL byte — check input encoding/source');\n  }\n  throw e;\n}","preventionTips":["Sanitize any path derived from untrusted input at the boundary.","Decode Buffers with the correct encoding and strip NUL padding.","Log-and-reject tainted values rather than trying to fix them silently."],"tags":["validation","path-injection","nul-byte"],"backgroundTag":"path-traversal-blocked","analyzedSha":"ac9a4e9abd8fd3058c070b72c23402a4f887929a","analyzedAt":"2026-09-15T23:29:44.066Z","contentChangedAt":"2026-09-15T23:29:44.066Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}