mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-04 11:01:16 +01:00
fix: preserve low-trust workspace isolation
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
ef1bf1a79b
commit
c1c3faf4d1
2 files changed
+57
-2
No files matched your search
@@ -41,6 +41,7 @@ import {
|
||||
stripHostWorkspaceProvisionForLowTrustSandbox,
|
||||
stripWorkspaceRuntimeFromExecutionRunConfig,
|
||||
shouldResetTaskSessionForModelChange,
|
||||
shouldReusePinnedExecutionWorkspaceForRun,
|
||||
stripConfiguredModelFromSessionParams,
|
||||
stripPaperclipSessionMetadataFromSessionParams,
|
||||
normalizeSessionParams,
|
||||
@@ -1660,6 +1661,33 @@ describe("effective run execution workspace config freshness", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("does not reuse an available shared pin for a low-trust isolated run", () => {
|
||||
expect(shouldReusePinnedExecutionWorkspaceForRun({
|
||||
requestedShouldReuseExisting: true,
|
||||
trustPresetKind: "low_trust_review",
|
||||
requestedExecutionWorkspaceMode: "isolated_workspace",
|
||||
existingExecutionWorkspaceMode: "shared_workspace",
|
||||
})).toBe(false);
|
||||
});
|
||||
|
||||
it("reuses an available isolated pin for a low-trust isolated run", () => {
|
||||
expect(shouldReusePinnedExecutionWorkspaceForRun({
|
||||
requestedShouldReuseExisting: true,
|
||||
trustPresetKind: "low_trust_review",
|
||||
requestedExecutionWorkspaceMode: "isolated_workspace",
|
||||
existingExecutionWorkspaceMode: "isolated_workspace",
|
||||
})).toBe(true);
|
||||
});
|
||||
|
||||
it("keeps unavailable low-trust pins on the named reuse-failure path", () => {
|
||||
expect(shouldReusePinnedExecutionWorkspaceForRun({
|
||||
requestedShouldReuseExisting: true,
|
||||
trustPresetKind: "low_trust_review",
|
||||
requestedExecutionWorkspaceMode: "isolated_workspace",
|
||||
existingExecutionWorkspaceMode: null,
|
||||
})).toBe(true);
|
||||
});
|
||||
|
||||
it.each([
|
||||
{ name: "missing", status: null },
|
||||
{ name: "archived", status: "archived" },
|
||||
|
||||
@@ -4355,6 +4355,25 @@ export function resolveExecutionWorkspaceReuseRequestForIssue(input: {
|
||||
};
|
||||
}
|
||||
|
||||
export function shouldReusePinnedExecutionWorkspaceForRun(input: {
|
||||
requestedShouldReuseExisting: boolean;
|
||||
trustPresetKind: TrustPresetResolution["kind"];
|
||||
requestedExecutionWorkspaceMode: ReturnType<typeof resolveExecutionWorkspaceMode>;
|
||||
existingExecutionWorkspaceMode: string | null;
|
||||
}): boolean {
|
||||
if (!input.requestedShouldReuseExisting) return false;
|
||||
|
||||
// A durable pin cannot weaken the low-trust isolation boundary. An available
|
||||
// non-isolated pin is bypassed so the policy can provision a fresh isolated workspace.
|
||||
// Missing or archived pins still flow through the named reuse-failure path.
|
||||
return !(
|
||||
input.trustPresetKind === "low_trust_review"
|
||||
&& input.requestedExecutionWorkspaceMode === "isolated_workspace"
|
||||
&& input.existingExecutionWorkspaceMode !== null
|
||||
&& input.existingExecutionWorkspaceMode !== "isolated_workspace"
|
||||
);
|
||||
}
|
||||
|
||||
export function resolveExecutionWorkspaceReuseProvisioningPolicy(input: {
|
||||
requestedShouldReuseExisting: boolean;
|
||||
workspaceConfigFreshness: ExecutionWorkspaceConfigFreshnessDecision;
|
||||
@@ -14020,8 +14039,16 @@ export function heartbeatService(db: Db, options: HeartbeatServiceOptions = {})
|
||||
issueExecutionWorkspacePreference: issueRef?.executionWorkspacePreference ?? null,
|
||||
existingExecutionWorkspaceStatus: existingExecutionWorkspace?.status ?? null,
|
||||
});
|
||||
const requestedShouldReuseExisting = workspaceReuseRequest.requestedShouldReuseExisting;
|
||||
const reusableExistingExecutionWorkspace = workspaceReuseRequest.existingExecutionWorkspaceAvailable
|
||||
const requestedShouldReuseExisting = shouldReusePinnedExecutionWorkspaceForRun({
|
||||
requestedShouldReuseExisting: workspaceReuseRequest.requestedShouldReuseExisting,
|
||||
trustPresetKind: trustPreset.kind,
|
||||
requestedExecutionWorkspaceMode,
|
||||
existingExecutionWorkspaceMode: workspaceReuseRequest.existingExecutionWorkspaceAvailable
|
||||
? existingExecutionWorkspace?.mode ?? null
|
||||
: null,
|
||||
});
|
||||
const reusableExistingExecutionWorkspace = requestedShouldReuseExisting
|
||||
&& workspaceReuseRequest.existingExecutionWorkspaceAvailable
|
||||
? existingExecutionWorkspace
|
||||
: null;
|
||||
if (
|
||||
|
||||
Reference in new issue
Block a user