abhigyanpatwari/GitNexus · error · InvalidStoragePathError
must not contain a NUL character.
Error message
${label} must not contain a NUL character. What it means
validateAbsolutePath rejects labeled absolute-path values that contain a NUL character, mirroring the repo-path check. NUL bytes terminate C-string paths and are a classic injection marker, so the resolver fails closed before any filesystem API runs.
Solutions
- Sanitize at the boundary: reject any value containing '\0' with a clear caller-side error.
- If from a Buffer, decode correctly (utf8) and strip trailing NULs before use.
- Regenerate corrupted metadata/config files instead of patching the tainted string.
Example fix
// before
root(userSuppliedPath);
// after
if (userSuppliedPath.includes('\0')) throw new Error('storage root must not contain NUL');
root(userSuppliedPath); Defensive patterns
Strategy: validation
Validate before calling
if (typeof value !== 'string' || value.includes('\0')) {
throw new Error(`${label} must not contain NUL characters`);
} Type guard
const isNulFreeString = (v: unknown): v is string => typeof v === 'string' && !v.includes('\0'); Try / catch
try {
return readOwnershipMetadata(value);
} catch (e) {
if (e instanceof InvalidStoragePathError && e.message.includes('NUL')) {
throw new Error(`${label} contained a NUL byte — regenerate the metadata file`);
}
throw e;
} Prevention
- Never pass raw Buffer slices or wide-encoded strings as paths without re-decoding.
- Validate all externally sourced paths for control characters.
- Regenerate corrupted ownership metadata instead of patching strings.
When it happens
Trigger: Calling resolved()/root()/readOwnershipMetadata() with a storage path containing '\0' — from unsanitized user input, wrong-encoding buffer decodes, or corrupted config/ownership metadata files.
Common situations: Ownership metadata files (.gitnexus) hand-edited or truncated at a NUL; HTTP-supplied storage paths passed straight through; byte-padded Windows path conversions.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- Repository path must not contain a NUL character.
- must not be blank.
- argument contains a double quote, unsafe for the Windows…
- argument contains NUL/CR/LF, unsafe for the Windows shell
- "asyncApiSpecPath" must be a non-empty string
AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-09-15).
Data as JSON: /api/errors/981358013decc25b.
Report an issue: GitHub.
Appendix: source
Thrown at gitnexus/src/storage/storage-resolver.ts:188
return code ? `${code}: ${(error as Error)?.message ?? String(error)}` : String(error);
};
const resolveRepoPath = (value: string): string => {
if (typeof value !== 'string' || value.length === 0) {
throw new InvalidStoragePathError('Repository path must be non-empty.');
}
if (value.includes('\0')) {
throw new InvalidStoragePathError('Repository path must not contain a NUL character.');
}
return path.resolve(value);
};
const validateAbsolutePath = (value: string, label: string): string => {
if (typeof value !== 'string' || value.length === 0) {
throw new InvalidStoragePathError(`${label} must be an absolute, non-empty path.`);
}
if (value.includes('\0')) {
throw new InvalidStoragePathError(`${label} must not contain a NUL character.`);
}
if (!path.isAbsolute(value)) {
throw new InvalidStoragePathError(`${label} must be an absolute path.`);
}
return path.resolve(value);
};
// Mirror registry lookup semantics without importing repo-manager and creating a cycle.
const canonicalRegistryPath = (value: string): string => {
const resolved = path.resolve(value);
try {
return stripWindowsLongPathPrefix(fs.realpathSync.native(resolved));
} catch {
return stripWindowsLongPathPrefix(resolved);
}
};
const canonicalRepoPath = (repoPath: string): string =>View on GitHub (pinned to ac9a4e9abd)