pi-better-sandbox 0.5.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/shared-sandbox-core.ts +11 -8
- package/shared-task-sandbox.ts +3 -1
package/package.json
CHANGED
package/shared-sandbox-core.ts
CHANGED
|
@@ -525,9 +525,8 @@ export function executableFromPath(name: string): string | undefined {
|
|
|
525
525
|
* afterwards because a resumed task re-runs the launch vector it captured and
|
|
526
526
|
* its `--ro-bind` sources have to still be there.
|
|
527
527
|
*
|
|
528
|
-
* Returns false when the placeholder could not be created.
|
|
529
|
-
*
|
|
530
|
-
* create is a path that process cannot create either.
|
|
528
|
+
* Returns false when the placeholder could not be created. Callers must fail
|
|
529
|
+
* closed for writable regions: a task may replace or chmod the blocking parent.
|
|
531
530
|
*/
|
|
532
531
|
function materializeDenyPath(path: string): boolean {
|
|
533
532
|
if (existsSync(path)) return true;
|
|
@@ -570,8 +569,9 @@ function buildLinuxSandboxCommand(
|
|
|
570
569
|
if (policy.permissions) return buildLinuxPermissionCommand(bwrap, args, policy, seams);
|
|
571
570
|
const materialize = seams.materializeDenyPath ?? materializeDenyPath;
|
|
572
571
|
const denyBinds = policy.denyWrite.flatMap((path) => {
|
|
573
|
-
const
|
|
574
|
-
|
|
572
|
+
const writable = writableInsideLinuxSandbox(path, policy.writableRoot);
|
|
573
|
+
if (writable && !materialize(path)) throw new Error(`Cannot protect denied path: ${path}`);
|
|
574
|
+
return [writable ? "--ro-bind" : "--ro-bind-try", path, path];
|
|
575
575
|
});
|
|
576
576
|
return {
|
|
577
577
|
file: bwrap,
|
|
@@ -583,8 +583,8 @@ function buildLinuxSandboxCommand(
|
|
|
583
583
|
// Layered last so a denied path wins over every writable bind above.
|
|
584
584
|
// A denied path need not exist yet, so one inside a writable region
|
|
585
585
|
// is materialized first; `-try` remains for the paths that are
|
|
586
|
-
// read-only regardless
|
|
587
|
-
//
|
|
586
|
+
// read-only regardless. A writable region whose guard cannot be
|
|
587
|
+
// materialized must fail before launching the task.
|
|
588
588
|
...denyBinds,
|
|
589
589
|
"--",
|
|
590
590
|
args.execPath, ...args.execArgs,
|
|
@@ -738,7 +738,10 @@ function buildLinuxPermissionCommand(
|
|
|
738
738
|
for (const writableRoot of [...(writableProject ? [project] : []),
|
|
739
739
|
...(policy.runtimeWrite ?? []).filter((path) => !compatibility.includes(path))]) {
|
|
740
740
|
const materialize = seams.materializeDenyPath ?? materializeDenyPath;
|
|
741
|
-
const leaves = protectedPaths.filter((path) => contains(writableRoot, path)
|
|
741
|
+
const leaves = protectedPaths.filter((path) => contains(writableRoot, path));
|
|
742
|
+
for (const path of leaves) {
|
|
743
|
+
if (!materialize(path)) throw new Error(`Cannot protect denied path: ${path}`);
|
|
744
|
+
}
|
|
742
745
|
for (const parent of protectedAncestors(leaves).filter((path) => contains(writableRoot, path) && path !== writableRoot)) {
|
|
743
746
|
writableAncestors.add(parent);
|
|
744
747
|
}
|
package/shared-task-sandbox.ts
CHANGED
|
@@ -160,6 +160,8 @@ export function installTaskTools(pi: ExtensionAPI, options: {
|
|
|
160
160
|
shellPath?: () => string | undefined;
|
|
161
161
|
trustedSources: readonly string[];
|
|
162
162
|
admitExtensionTool?: (name: string, input: unknown, sourcePath: string | undefined) => boolean;
|
|
163
|
+
/** Build the admitted bash definition from the confined operations (default: the SDK bash tool). */
|
|
164
|
+
bashDefinition?: (cwd: string, operations: BashOperations) => ReturnType<typeof createBashToolDefinition>;
|
|
163
165
|
}) {
|
|
164
166
|
const { controller } = options;
|
|
165
167
|
const sourceKey = (path: string) => path.startsWith("<") ? path : canonicalizePath(path);
|
|
@@ -180,7 +182,7 @@ export function installTaskTools(pi: ExtensionAPI, options: {
|
|
|
180
182
|
pi.registerTool(own(createReadToolDefinition(cwd, { operations: files.read })));
|
|
181
183
|
pi.registerTool(own(createWriteToolDefinition(cwd, { operations: files.write })));
|
|
182
184
|
pi.registerTool(own(createEditToolDefinition(cwd, { operations: files.edit })));
|
|
183
|
-
pi.registerTool(own(createBashToolDefinition(cwd, { operations: bash })));
|
|
185
|
+
pi.registerTool(own(options.bashDefinition ? options.bashDefinition(cwd, bash) : createBashToolDefinition(cwd, { operations: bash })));
|
|
184
186
|
};
|
|
185
187
|
register(options.cwd);
|
|
186
188
|
pi.on("user_bash", () => ({ operations: bash }));
|