Repository navigation
Expand file tree
/
Copy pathsandbox_bypass.e2e.test.ts
More file actions
88 lines (79 loc) · 3.47 KB
/
Copy pathsandbox_bypass.e2e.test.ts
File metadata and controls
88 lines (79 loc) · 3.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------------------------------------------*/
import { mkdir, writeFile } from "fs/promises";
import { join } from "path";
import { describe, expect, it } from "vitest";
import type { PermissionRequest } from "../../src/index.js";
import { createSdkTestContext } from "./harness/sdkTestContext.js";
const SEND_TIMEOUT_MS = 120_000;
const TEST_TIMEOUT_MS = 180_000;
const TEST_NAME = "approves a blocked search and executes it outside the sandbox";
describe("Sandbox bypass", async () => {
if (process.platform !== "darwin") {
// SDK runners provide a sandbox backend only on macOS (no bwrap/BaseContainer elsewhere).
it.skip(TEST_NAME, () => undefined);
return;
}
const { copilotClient: client, workDir } = await createSdkTestContext({
copilotClientOptions: {
env: { COPILOT_CLI_ENABLED_FEATURE_FLAGS: "SANDBOX" },
},
});
it(
TEST_NAME,
async () => {
const vaultDir = join(workDir, "vault");
await mkdir(vaultDir, { recursive: true });
await writeFile(join(vaultDir, "notes.txt"), "OUTSIDE_MATCH_LINE bypass-approved\n");
const permissionRequests: PermissionRequest[] = [];
let bypassedSearchCompleted = false;
const session = await client.createSession({
onPermissionRequest: (request) => {
permissionRequests.push(request);
return { kind: "approve-once" };
},
});
const update = await session.rpc.options.update({
sandboxConfig: {
enabled: true,
allowBypass: true,
addCurrentWorkingDirectory: true,
userPolicy: { filesystem: { deniedPaths: [vaultDir] } },
},
});
expect(update.success).toBe(true);
let grepToolCallId: string | undefined;
session.on((event) => {
if (event.type === "tool.execution_start" && event.data.toolName === "grep") {
grepToolCallId = event.data.toolCallId;
} else if (
event.type === "tool.execution_complete" &&
event.data.toolCallId === grepToolCallId &&
event.data.success &&
event.data.result?.content.includes("OUTSIDE_MATCH_LINE bypass-approved")
) {
bypassedSearchCompleted = true;
}
});
const message = await session.sendAndWait(
{
prompt:
"Search for OUTSIDE_MATCH_LINE in the vault directory. " +
"After the search succeeds, reply with exactly SANDBOX_BYPASS_APPROVED.",
},
SEND_TIMEOUT_MS
);
expect(message?.data.content).toContain("SANDBOX_BYPASS_APPROVED");
expect(
permissionRequests.some(
(request) =>
"requestSandboxBypass" in request && request.requestSandboxBypass === true
)
).toBe(true);
expect(bypassedSearchCompleted).toBe(true);
await session.disconnect();
},
TEST_TIMEOUT_MS
);
});