fix: tighten path guard coverage

This commit is contained in:
Peter Steinberger 2026-03-13 23:37:31 +00:00
parent bff340c1ca
commit ff6636ed5b
2 changed files with 35 additions and 6 deletions

View File

@ -1,4 +1,4 @@
import { describe, expect, it } from "vitest";
import { afterEach, describe, expect, it } from "vitest";
import {
hasNodeErrorCode,
isNodeError,
@ -8,6 +8,21 @@ import {
normalizeWindowsPathForComparison,
} from "./path-guards.js";
const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, "platform");
function setPlatform(platform: NodeJS.Platform): void {
Object.defineProperty(process, "platform", {
value: platform,
configurable: true,
});
}
afterEach(() => {
if (originalPlatformDescriptor) {
Object.defineProperty(process, "platform", originalPlatformDescriptor);
}
});
describe("normalizeWindowsPathForComparison", () => {
it("normalizes extended-length and UNC windows paths", () => {
expect(normalizeWindowsPathForComparison("\\\\?\\C:\\Users\\Peter/Repo")).toBe(
@ -47,4 +62,19 @@ describe("isPathInside", () => {
expect(isPathInside("/workspace/root", "/workspace/root/nested/file.txt")).toBe(true);
expect(isPathInside("/workspace/root", "/workspace/root/../escape.txt")).toBe(false);
});
it("uses win32 path semantics for windows containment checks", () => {
setPlatform("win32");
expect(isPathInside(String.raw`C:\workspace\root`, String.raw`C:\workspace\root`)).toBe(true);
expect(
isPathInside(String.raw`C:\workspace\root`, String.raw`C:\workspace\root\Nested\File.txt`),
).toBe(true);
expect(
isPathInside(String.raw`C:\workspace\root`, String.raw`C:\workspace\root\..\escape.txt`),
).toBe(false);
expect(
isPathInside(String.raw`C:\workspace\root`, String.raw`D:\workspace\root\file.txt`),
).toBe(false);
});
});

View File

@ -33,16 +33,15 @@ export function isSymlinkOpenError(value: unknown): boolean {
}
export function isPathInside(root: string, target: string): boolean {
const resolvedRoot = path.resolve(root);
const resolvedTarget = path.resolve(target);
if (process.platform === "win32") {
const rootForCompare = normalizeWindowsPathForComparison(resolvedRoot);
const targetForCompare = normalizeWindowsPathForComparison(resolvedTarget);
const rootForCompare = normalizeWindowsPathForComparison(path.win32.resolve(root));
const targetForCompare = normalizeWindowsPathForComparison(path.win32.resolve(target));
const relative = path.win32.relative(rootForCompare, targetForCompare);
return relative === "" || (!relative.startsWith("..") && !path.win32.isAbsolute(relative));
}
const resolvedRoot = path.resolve(root);
const resolvedTarget = path.resolve(target);
const relative = path.relative(resolvedRoot, resolvedTarget);
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
}