// tools/sanitize-path.ts — Path sanitization to prevent directory traversal attacks.
// Validates that resolved paths fall within allowed directory prefixes.
import { resolve, normalize } from 'node:path';
import { homedir, tmpdir } from 'node:os';
import { realpathSync } from 'node:fs';
/**
 * Returns the list of allowed directory prefixes.
 * Paths must start with one of these to be considered safe.
 * Uses os.tmpdir() to handle macOS symlinks (/var/folders/... vs /tmp).
 */
function getSafePrefixes() {
    const prefixes = [homedir(), process.cwd()];
    // Add both the logical and resolved tmpdir (macOS: /tmp → /private/tmp, tmpdir() → /var/folders/...)
    try {
        const tmp = tmpdir();
        prefixes.push(tmp);
        prefixes.push(realpathSync(tmp));
    }
    catch {
        prefixes.push('/tmp');
    }
    // Always include /tmp (symlink to /private/tmp on macOS) and its realpath
    prefixes.push('/tmp');
    try {
        prefixes.push(realpathSync('/tmp'));
    }
    catch {
        // ignore if /tmp doesn't exist
    }
    return [...new Set(prefixes)];
}
/**
 * Sanitizes an input path to prevent directory traversal attacks.
 *
 * - Normalizes and resolves the path to an absolute form
 * - Rejects paths that still contain ".." after resolution
 * - Rejects paths outside allowed directories (home, /tmp, cwd)
 *
 * @param inputPath - The untrusted path from an MCP client
 * @returns The resolved, validated absolute path
 * @throws Error if the path is unsafe or outside allowed directories
 */
export function sanitizePath(inputPath) {
    if (!inputPath || inputPath.trim() === '') {
        throw new Error('Path must not be empty');
    }
    const resolved = resolve(normalize(inputPath));
    // After resolve(), ".." segments should be eliminated on valid filesystems.
    // If they persist, something is wrong.
    if (resolved.includes('..')) {
        throw new Error(`Unsafe path: resolved path still contains ".." segments: ${resolved}`);
    }
    const safePrefixes = getSafePrefixes();
    const isSafe = safePrefixes.some((prefix) => resolved.startsWith(prefix));
    if (!isSafe) {
        throw new Error(`Path outside allowed directories: ${resolved}. Allowed prefixes: ${safePrefixes.join(', ')}`);
    }
    return resolved;
}
//# sourceMappingURL=sanitize-path.js.map