fix(plugins): detect install root rebinding

This commit is contained in:
Peter Steinberger
2026-04-27 20:47:49 +01:00
parent f6b2ba4a10
commit 5a23032adb
2 changed files with 19 additions and 7 deletions

View File

@@ -218,7 +218,7 @@ describe("installPackageDir", () => {
installBaseDir,
preservedDir: preservedInstallRoot,
outsideTarget: outsideInstallRoot,
rebindAtCall: 3,
rebindAtCall: 4,
run: async () => {
await expect(
installPackageDir({
@@ -259,7 +259,7 @@ describe("installPackageDir", () => {
installBaseDir,
preservedDir: preservedInstallRoot,
outsideTarget: outsideInstallRoot,
rebindAtCall: 7,
rebindAtCall: 8,
run: async () =>
await installPackageDir({
sourceDir,

View File

@@ -170,11 +170,17 @@ export async function installPackageDir(params: {
}): Promise<{ ok: true } | { ok: false; error: string; code?: string }> {
params.logger?.info?.(`Installing to ${params.targetDir}`);
const installBaseDir = path.dirname(params.targetDir);
await fs.mkdir(installBaseDir, { recursive: true });
await assertInstallBoundaryPaths({
installBaseDir,
candidatePaths: [params.targetDir],
});
let initialInstallBaseRealPath: string;
try {
await fs.mkdir(installBaseDir, { recursive: true });
initialInstallBaseRealPath = await fs.realpath(installBaseDir);
await assertInstallBoundaryPaths({
installBaseDir,
candidatePaths: [params.targetDir],
});
} catch (err) {
return { ok: false, error: `${params.copyErrorPrefix}: ${String(err)}` };
}
let installBaseRealPath: string;
let canonicalTargetDir: string;
try {
@@ -182,7 +188,13 @@ export async function installPackageDir(params: {
installBaseDir,
targetDir: params.targetDir,
}));
if (installBaseRealPath !== initialInstallBaseRealPath) {
throw new Error(INSTALL_BASE_CHANGED_ERROR_MESSAGE);
}
} catch (err) {
if (isInstallBaseChangedError(err)) {
params.logger?.warn?.(INSTALL_BASE_CHANGED_ABORT_WARNING);
}
return { ok: false, error: `${params.copyErrorPrefix}: ${String(err)}` };
}