fix(sandbox): allow mkdirp boundary checks on existing directories (#31547)

This commit is contained in:
Peter Steinberger
2026-03-02 15:52:30 +00:00
parent 6135eb3353
commit dec2c9e74d
2 changed files with 53 additions and 19 deletions

View File

@@ -267,25 +267,12 @@ class SandboxFsBridgeImpl implements SandboxFsBridge {
});
if (!guarded.ok) {
if (guarded.reason !== "path") {
// mkdirp may legally target an already-existing directory. Keep a
// directory-only fallback so boundary checks remain strict for files
// while avoiding false negatives from file-oriented open validation.
if (options.allowedType === "directory") {
try {
const st = fs.statSync(target.hostPath);
if (!st.isDirectory()) {
throw new Error(
`Sandbox boundary checks failed; cannot ${options.action}: ${target.containerPath}`,
);
}
} catch {
throw guarded.error instanceof Error
? guarded.error
: new Error(
`Sandbox boundary checks failed; cannot ${options.action}: ${target.containerPath}`,
);
}
} else {
// Some platforms cannot open directories via openSync(O_RDONLY), even when
// the path is a valid in-boundary directory. Allow mkdirp to proceed in that
// narrow case by verifying the host path is an existing directory.
const canFallbackToDirectoryStat =
options.allowedType === "directory" && this.pathIsExistingDirectory(target.hostPath);
if (!canFallbackToDirectoryStat) {
throw guarded.error instanceof Error
? guarded.error
: new Error(
@@ -314,6 +301,14 @@ class SandboxFsBridgeImpl implements SandboxFsBridge {
}
}
private pathIsExistingDirectory(hostPath: string): boolean {
try {
return fs.statSync(hostPath).isDirectory();
} catch {
return false;
}
}
private resolveMountByContainerPath(containerPath: string): SandboxFsMount | null {
const normalized = normalizeContainerPath(containerPath);
for (const mount of this.mountsByContainer) {