The isWithinHome() check used path.relative() which is purely string-based and does not follow symlinks. A symlink inside the home directory pointing to an external path would bypass the containment check, allowing directory listing of arbitrary filesystem locations. Now uses fs.realpathSync() to resolve symlinks before the containment comparison, ensuring the real filesystem path is validated. Co-authored-by: ThankNIXlater <ThankNIXlater@users.noreply.github.com>
This commit is contained in:
@@ -42,8 +42,18 @@ const normalizeQuery = (query: string): string => {
|
|||||||
return `~/${withoutLeading}`;
|
return `~/${withoutLeading}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const resolveRealPath = (value: string): string => {
|
||||||
|
try {
|
||||||
|
return fs.realpathSync(value);
|
||||||
|
} catch {
|
||||||
|
return path.resolve(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const isWithinHome = (target: string, home: string): boolean => {
|
const isWithinHome = (target: string, home: string): boolean => {
|
||||||
const relative = path.relative(home, target);
|
const resolvedTarget = resolveRealPath(target);
|
||||||
|
const resolvedHome = resolveRealPath(home);
|
||||||
|
const relative = path.relative(resolvedHome, resolvedTarget);
|
||||||
if (!relative) return true;
|
if (!relative) return true;
|
||||||
return !relative.startsWith("..") && !path.isAbsolute(relative);
|
return !relative.startsWith("..") && !path.isAbsolute(relative);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user