@iflow-mcp/ejmockler-brutalist
Version:
Deploy Claude, Codex & Gemini CLI agents to demolish your work before users do. Real file analysis. Brutal honesty. Now with conversation continuation & intelligent pagination.
51 lines • 2.19 kB
JavaScript
import { resolve, sep } from 'path';
import { promises as fs } from 'fs';
/**
* Resolves a given path and validates that it is within the allowed project root.
* Prevents path traversal attacks.
* @param projectRoot The absolute path to the project root directory.
* @param userPath The user-provided path (can be relative or absolute).
* @param mustExist If true, the resolved path must exist on the filesystem.
* @returns The resolved, validated absolute path.
* @throws Error if the path is outside the project root or does not exist (if mustExist is true).
*/
export async function resolveAndValidatePath(projectRoot, userPath, mustExist = false) {
// Check for null byte injection before any path operations
if (userPath.includes('\0')) {
throw new Error(`Path traversal detected`);
}
const absoluteProjectRoot = await fs.realpath(projectRoot);
// For absolute paths, check if they start outside project root immediately
if (resolve(userPath) === userPath) { // userPath is absolute
if (!userPath.startsWith(absoluteProjectRoot + sep) && userPath !== absoluteProjectRoot) {
throw new Error(`Path traversal detected`);
}
}
const resolvedPath = resolve(absoluteProjectRoot, userPath);
let absoluteResolvedPath;
let pathExists = false;
try {
await fs.access(resolvedPath);
pathExists = true;
}
catch {
pathExists = false;
}
if (pathExists) {
// Use fs.realpath to resolve symlinks and detect traversal for existing paths
absoluteResolvedPath = await fs.realpath(resolvedPath);
}
else {
// For non-existent paths, use logical resolution for traversal detection
absoluteResolvedPath = resolvedPath;
}
// Ensure the resolved path is a sub-path of the project root
if (!absoluteResolvedPath.startsWith(absoluteProjectRoot + sep) && absoluteResolvedPath !== absoluteProjectRoot) {
throw new Error(`Path traversal detected`);
}
if (mustExist && !pathExists) {
throw new Error(`Path does not exist: ${userPath}`);
}
return absoluteResolvedPath;
}
//# sourceMappingURL=utils.js.map