Merge pull request #3254 from wingding12/fix/filesystem-macos-symlink-path-resolution

fix(filesystem): resolve symlinked allowed directories to both forms
This commit is contained in:
Ola Hungerford
2026-02-19 07:36:47 -07:00
committed by GitHub
2 changed files with 61 additions and 4 deletions

View File

@@ -39,22 +39,32 @@ if (args.length === 0) {
}
// Store allowed directories in normalized and resolved form
let allowedDirectories = await Promise.all(
// We store BOTH the original path AND the resolved path to handle symlinks correctly
// This fixes the macOS /tmp -> /private/tmp symlink issue where users specify /tmp
// but the resolved path is /private/tmp
let allowedDirectories = (await Promise.all(
args.map(async (dir) => {
const expanded = expandHome(dir);
const absolute = path.resolve(expanded);
const normalizedOriginal = normalizePath(absolute);
try {
// Security: Resolve symlinks in allowed directories during startup
// This ensures we know the real paths and can validate against them later
const resolved = await fs.realpath(absolute);
return normalizePath(resolved);
const normalizedResolved = normalizePath(resolved);
// Return both original and resolved paths if they differ
// This allows matching against either /tmp or /private/tmp on macOS
if (normalizedOriginal !== normalizedResolved) {
return [normalizedOriginal, normalizedResolved];
}
return [normalizedResolved];
} catch (error) {
// If we can't resolve (doesn't exist), use the normalized absolute path
// This allows configuring allowed dirs that will be created later
return normalizePath(absolute);
return [normalizedOriginal];
}
})
);
)).flat();
// Filter to only accessible directories, warn about inaccessible ones
const accessibleDirectories: string[] = [];