refactor: unify boundary-safe reads for bootstrap and includes

This commit is contained in:
Peter Steinberger
2026-02-26 12:42:06 +01:00
parent 199ef9f8ea
commit 242188b7b1
8 changed files with 374 additions and 100 deletions

View File

@@ -1,8 +1,6 @@
import {
assertNoPathAliasEscape,
PATH_ALIAS_POLICIES,
type PathAliasPolicy,
} from "../../infra/path-alias-guards.js";
import fs from "node:fs";
import { openBoundaryFile } from "../../infra/boundary-file-read.js";
import { PATH_ALIAS_POLICIES, type PathAliasPolicy } from "../../infra/path-alias-guards.js";
import { execDockerRaw, type ExecDockerRawResult } from "./docker.js";
import {
buildSandboxFsMounts,
@@ -24,6 +22,7 @@ type PathSafetyOptions = {
action: string;
aliasPolicy?: PathAliasPolicy;
requireWritable?: boolean;
allowMissingTarget?: boolean;
};
export type SandboxResolvedPath = {
@@ -254,12 +253,23 @@ class SandboxFsBridgeImpl implements SandboxFsBridge {
);
}
await assertNoPathAliasEscape({
const guarded = await openBoundaryFile({
absolutePath: target.hostPath,
rootPath: lexicalMount.hostRoot,
boundaryLabel: "sandbox mount root",
policy: options.aliasPolicy,
aliasPolicy: options.aliasPolicy,
});
if (!guarded.ok) {
if (guarded.reason !== "path" || options.allowMissingTarget === false) {
throw guarded.error instanceof Error
? guarded.error
: new Error(
`Sandbox boundary checks failed; cannot ${options.action}: ${target.containerPath}`,
);
}
} else {
fs.closeSync(guarded.fd);
}
const canonicalContainerPath = await this.resolveCanonicalContainerPath({
containerPath: target.containerPath,