chore: initialize qiming workspace repository

This commit is contained in:
Codex
2026-05-29 14:22:48 +08:00
commit bfd67a0f2c
10750 changed files with 1885711 additions and 0 deletions

View File

@@ -0,0 +1,196 @@
/**
* Linux bwrap 沙箱集成测试
*
* 使用 --ro-bind / / --tmpfs /tmp --unshare-net无网络
* 验证危险操作被正确拦截。
*
* 运行条件:
* - platform === linux
* - bwrap 命令可用
*/
import { exec } from "child_process";
import { existsSync } from "fs";
import { describe, it, expect, beforeAll } from "vitest";
const testOnLinux = process.platform === "linux" ? describe : describe.skip;
let bwrapAvailable = false;
let workspaceDir = "/tmp/test-bwrap-workspace";
beforeAll(async () => {
try {
const { stdout } = await exec("which bwrap");
bwrapAvailable = stdout.trim().length > 0;
} catch {
bwrapAvailable = false;
}
// 创建测试工作区
await exec(`mkdir -p ${workspaceDir}`).catch(() => {});
});
const BASE_BWRAP_ARGS_NO_NET = [
"--die-with-parent",
"--new-session",
"--unshare-user-try",
"--unshare-pid",
"--unshare-uts",
"--unshare-cgroup-try",
"--unshare-net",
"--dev-bind", "/dev", "/dev",
"--proc", "/proc",
"--tmpfs", "/tmp",
"--ro-bind", "/", "/",
"--bind", workspaceDir, workspaceDir,
"--chdir", workspaceDir,
];
testOnLinux("Linux bwrap integration tests", () => {
// ==================== 文件写入测试 ====================
describe("file write operations", () => {
it("should BLOCK writing to /etc/hosts", async () => {
const result = await runBwrapCommand(`echo test >> /etc/hosts`);
expectBlocked(result);
});
it("should BLOCK writing to /etc/passwd", async () => {
const result = await runBwrapCommand(`echo test >> /etc/passwd`);
expectBlocked(result);
});
it("should BLOCK writing to /usr/bin/", async () => {
const result = await runBwrapCommand(`touch /usr/bin/evil-binary`);
expectBlocked(result);
});
it("should BLOCK writing to /home/", async () => {
const result = await runBwrapCommand(`touch /home/exfil.txt`);
expectBlocked(result);
});
it("should ALLOW writing inside workspace", async () => {
const result = await runBwrapCommand(`echo safe > ${workspaceDir}/safe.txt`);
expectAllowed(result);
});
it("should ALLOW writing to /tmp/ (tmpfs)", async () => {
const result = await runBwrapCommand(`echo tmpfs > /tmp/bwrap-tmp-test.txt && cat /tmp/bwrap-tmp-test.txt`);
expectAllowed(result);
});
it("should verify /tmp/ write is in tmpfs not host", async () => {
// 验证 /tmp 是 tmpfs宿主 /tmp 不会有这个文件
await runBwrapCommand(`echo isolated > /tmp/unique-bwrap-test.txt`);
const { stdout } = await exec(`cat /tmp/unique-bwrap-test.txt 2>&1 || echo "FILE_NOT_FOUND"`);
// 宿主 /tmp 不应有此文件(因为是 tmpfs
expect(stdout.trim()).toBe("FILE_NOT_FOUND");
});
});
// ==================== 文件删除测试 ====================
describe("file delete operations", () => {
it("should BLOCK deleting /etc/hostname", async () => {
const result = await runBwrapCommand(`rm /etc/hostname 2>&1 || true`);
expectBlocked(result);
});
it("should BLOCK deleting /bin/sh", async () => {
const result = await runBwrapCommand(`rm /bin/sh 2>&1 || true`);
expectBlocked(result);
});
});
// ==================== 网络测试 ====================
describe("network access", () => {
it("should BLOCK external network (--unshare-net)", async () => {
const result = await runBwrapCommand(`curl -s --max-time 5 http://example.com 2>&1 || true`);
expectBlocked(result);
});
it("should ALLOW loopback (localhost still accessible)", async () => {
// --unshare-net 后 lo 仍可用localhost 应该能工作
const result = await runBwrapCommand(`ping -c 1 127.0.0.1 2>&1 || true`);
// ping 可能有其他限制,只要不是 "network unreachable" 就行
const blocked = /network.unreachable|no.route|operation.not.permitted/i.test(result.stderr + result.stdout);
// 注意:某些环境下 ping 需要 CAP_NET_RAW可能被阻止
// 宽松处理:网络操作失败是预期的
expect(result.exitCode !== 0 || blocked).toBe(true);
});
});
// ==================== 提权测试 ====================
describe("privilege escalation", () => {
it("should BLOCK sudo id", async () => {
const result = await runBwrapCommand(`sudo id 2>&1 || true`);
expect(result.exitCode !== 0 || /permission|denied/i.test(result.stderr + result.stdout)).toBe(true);
});
});
// ==================== 系统命令测试 ====================
describe("system commands", () => {
it("should BLOCK reboot", async () => {
const result = await runBwrapCommand(`reboot 2>&1 || true`);
expectBlocked(result);
});
it("should BLOCK halt", async () => {
const result = await runBwrapCommand(`halt 2>&1 || true`);
expectBlocked(result);
});
});
// ==================== /dev gap 测试 ====================
describe("/dev access gap", () => {
it("should BLOCK mknod", async () => {
const result = await runBwrapCommand(`mknod /dev/test-device c 1 5 2>&1 || true`);
expectBlocked(result);
});
it("should BLOCK writing to /dev/sda", async () => {
const result = await runBwrapCommand(`echo evil > /dev/sda 2>&1 || true`);
expectBlocked(result);
});
});
// ==================== PID 命名空间测试 ====================
describe("PID namespace isolation", () => {
it("should show few processes (PID namespace isolated)", async () => {
const result = await runBwrapCommand(`ps aux | wc -l`);
const count = parseInt(result.stdout.trim(), 10);
// 在隔离的 PID 命名空间中,进程数应该很少(远少于宿主机的进程数)
expect(count).toBeLessThan(20);
});
});
});
// Helper
async function runBwrapCommand(command: string): Promise<{ exitCode: number; stdout: string; stderr: string }> {
const { exec } = await import("child_process");
const { promisify } = await import("util");
const execAsync = promisify(exec);
try {
const { stdout, stderr, code } = await execAsync(
`bwrap ${BASE_BWRAP_ARGS_NO_NET.join(" ")} /bin/sh -c '${command.replace(/'/g, "'\\''")}'`,
{ timeout: 10000 }
);
return { exitCode: code ?? 0, stdout: stdout ?? "", stderr: stderr ?? "" };
} catch (e: any) {
return { exitCode: e.code ?? 1, stdout: e.stdout ?? "", stderr: e.stderr ?? e.message };
}
}
// 从 shared-imports 复用 expectBlocked/expectAllowed
function expectBlocked(result: { exitCode: number; stdout: string; stderr: string }): void {
const blocked = result.exitCode !== 0 ||
/permission|operation not permitted|denied|not allowed|read-only/i.test(result.stderr) ||
/permission|operation not permitted|denied|not allowed|read-only/i.test(result.stdout);
if (!blocked) {
throw new Error(`Expected blocked, got exitCode=${result.exitCode}`);
}
}
function expectAllowed(result: { exitCode: number; stdout: string; stderr: string }): void {
if (result.exitCode !== 0) {
throw new Error(`Expected allowed, got exitCode=${result.exitCode}: ${result.stderr}`);
}
}

View File

@@ -0,0 +1,146 @@
/**
* macOS Seatbelt 沙箱集成测试
*
* 使用与生产完全一致的 seatbelt profile 格式(无 network*
* 验证危险操作被正确拦截。
*
* 运行条件:
* - platform === darwin
* - /usr/bin/sandbox-exec 存在
*/
import { existsSync, mkdirSync } from "fs";
import { execSync } from "child_process";
import { describe, it, expect, beforeAll } from "vitest";
import { runInSeatbelt, expectBlocked, expectAllowed } from "./shared-integration-utils";
const testOnMacOS = process.platform === "darwin" && existsSync("/usr/bin/sandbox-exec") ? describe : describe.skip;
const WORKSPACE_DIR = "/tmp/test-seatbelt-workspace";
const WORKSPACE_DIR_REALPATH = "/private/tmp/test-seatbelt-workspace";
// 确保 workspace 目录存在(宿主上)
beforeAll(() => {
try {
mkdirSync(WORKSPACE_DIR, { recursive: true });
} catch {}
});
const SEATBELT_PROFILE_NO_NETWORK = `(version 1)
(deny default)
(allow file-read*)
(allow process-exec (regex #"^/usr/bin/"))
(allow process-exec (regex #"^/bin/"))
(allow process-exec (regex #"^/usr/lib/"))
(allow process-fork)
(allow signal (target self))
(allow sysctl-read)
(allow mach-lookup)
(allow ipc-posix*)
(allow file-lock)
(allow file-write* (subpath "${WORKSPACE_DIR}"))
(allow file-write* (subpath "${WORKSPACE_DIR_REALPATH}"))
(allow file-write* (literal "/dev/null"))
(allow file-write* (literal "/dev/dtracehelper"))
(allow file-write* (literal "/dev/urandom"))
`;
const SEATBELT_PROFILE_WITH_NETWORK = SEATBELT_PROFILE_NO_NETWORK + "(allow network*)\n";
testOnMacOS("macOS seatbelt integration tests", () => {
// ==================== 文件写入测试 ====================
describe("file write operations", () => {
it("should BLOCK writing to /etc/hosts", async () => {
const result = await runInSeatbelt(SEATBELT_PROFILE_NO_NETWORK, "echo test >> /etc/hosts");
expectBlocked(result);
});
it("should BLOCK writing to /etc/passwd", async () => {
const result = await runInSeatbelt(SEATBELT_PROFILE_NO_NETWORK, "echo test >> /etc/passwd");
expectBlocked(result);
});
it("should BLOCK writing to /usr/bin/", async () => {
const result = await runInSeatbelt(SEATBELT_PROFILE_NO_NETWORK, "touch /usr/bin/evil-binary");
expectBlocked(result);
});
it("should BLOCK writing to ~/Documents/", async () => {
const result = await runInSeatbelt(SEATBELT_PROFILE_NO_NETWORK, "touch ~/Documents/exfil.txt");
expectBlocked(result);
});
it("should BLOCK writing to /tmp/ (not in writablePaths)", async () => {
const result = await runInSeatbelt(SEATBELT_PROFILE_NO_NETWORK, "touch /tmp/attacker-file.txt");
expectBlocked(result);
});
it("should ALLOW writing inside workspace", async () => {
// Workspace dir is pre-created by beforeAll on host.
// Only the write operation runs inside sandbox (mkdir already succeeded on host).
const result = await runInSeatbelt(SEATBELT_PROFILE_NO_NETWORK, "echo safe > /tmp/test-seatbelt-workspace/safe.txt");
expectAllowed(result);
});
});
// ==================== 文件删除测试 ====================
describe("file delete operations", () => {
it("should BLOCK deleting /etc/resolv.conf", async () => {
const result = await runInSeatbelt(SEATBELT_PROFILE_NO_NETWORK, "rm /etc/resolv.conf 2>&1 || true");
expectBlocked(result);
});
it("should BLOCK deleting /usr/bin/ls", async () => {
// Note: On SIP-protected systems, /usr/bin/ls can't be deleted anyway (SIP, not sandbox)
// We still expect blocked for other reasons
const result = await runInSeatbelt(SEATBELT_PROFILE_NO_NETWORK, "rm /usr/bin/ls 2>&1 || true");
// Just verify some error occurred (either sandbox or system)
const blocked = result.exitCode !== 0 || /permission|denied|not allowed|no such file/i.test(result.stderr + result.stdout);
expect(blocked).toBe(true);
});
});
// ==================== 提权测试 ====================
describe("privilege escalation", () => {
it("should BLOCK sudo id - sandbox denies exec", async () => {
// Without || true, exit code reflects sandbox failure
const result = await runInSeatbelt(SEATBELT_PROFILE_NO_NETWORK, "sudo id 2>&1");
// sandbox denies exec of sudo → "Operation not permitted"
const blocked = result.exitCode !== 0 ||
/permission|denied|not allowed|operation not permitted/i.test(result.stderr + result.stdout);
expect(blocked).toBe(true);
});
});
// ==================== 系统命令测试 ====================
describe("system commands", () => {
it("should BLOCK shutdown - permission denied by sandbox", async () => {
// Without || true, the actual exit code will be captured
const result = await runInSeatbelt(SEATBELT_PROFILE_NO_NETWORK, "/sbin/shutdown -h now 2>&1");
// sandbox blocks exec of /sbin/shutdown → "Operation not permitted"
const blocked = result.exitCode !== 0 ||
/permission|denied|not allowed|operation not permitted/i.test(result.stderr + result.stdout);
expect(blocked).toBe(true);
});
});
// ==================== 网络测试 ====================
describe("network access", () => {
it("should BLOCK network access (no network* profile)", async () => {
// Use curl without -s to see error messages; no || true so exitCode reflects curl
const result = await runInSeatbelt(SEATBELT_PROFILE_NO_NETWORK, "curl --max-time 5 http://example.com 2>&1");
// curl exit 6 = Could not resolve host (DNS blocked by sandbox)
const blocked = result.exitCode !== 0 ||
/could not resolve|failed|connection|network|permission/i.test(result.stderr + result.stdout);
expect(blocked).toBe(true);
});
it("should ALLOW network access (with network* profile)", async () => {
// With network* allowed, curl error would be non-permission (e.g., exit 6 = DNS fail)
const result = await runInSeatbelt(SEATBELT_PROFILE_WITH_NETWORK, "curl --max-time 10 http://example.com 2>&1");
// If exit is non-zero, it should NOT be due to permission denied by sandbox
if (result.exitCode !== 0) {
expect(/permission|denied.*network|operation not permitted/i.test(result.stderr + result.stdout)).toBe(false);
}
});
});
});

View File

@@ -0,0 +1,91 @@
import { exec } from "child_process";
import { promisify } from "util";
const execAsync = promisify(exec);
export interface ExecResult {
exitCode: number;
stdout: string;
stderr: string;
timedOut: boolean;
}
const TIMEOUT_MS = 10000;
/**
* 在 macOS seatbelt profile 下执行命令
*/
export async function runInSeatbelt(
profileContent: string,
shellCommand: string,
): Promise<ExecResult> {
const tmpProfile = `/tmp/qiming-test-${Date.now()}.sb`;
const cmd = `echo '${profileContent.replace(/'/g, "'\\''")}' > ${tmpProfile} && sandbox-exec -f ${tmpProfile} /bin/sh -c '${shellCommand.replace(/'/g, "'\\''")}' ; rm -f ${tmpProfile}`;
try {
const { stdout, stderr, signal, code } = await execAsync(cmd, {
timeout: TIMEOUT_MS,
shell: "/bin/sh",
});
return {
exitCode: code ?? 0,
stdout: stdout ?? "",
stderr: stderr ?? "",
timedOut: signal === "SIGTERM",
};
} catch (e: any) {
return {
exitCode: e.code ?? 1,
stdout: e.stdout ?? "",
stderr: e.stderr ?? e.message ?? "",
timedOut: e.signal === "SIGTERM",
};
}
}
/**
* 在 bwrap 下执行命令
*/
export async function runInBwrap(
bwrapArgs: string[],
shellCommand: string,
): Promise<ExecResult> {
try {
const { stdout, stderr, signal, code } = await execAsync(
`bwrap ${bwrapArgs.join(" ")} /bin/sh -c '${shellCommand.replace(/'/g, "'\\''")}'`,
{ timeout: TIMEOUT_MS, shell: "/bin/sh" }
);
return {
exitCode: code ?? 0,
stdout: stdout ?? "",
stderr: stderr ?? "",
timedOut: signal === "SIGTERM",
};
} catch (e: any) {
return {
exitCode: e.code ?? 1,
stdout: e.stdout ?? "",
stderr: e.stderr ?? e.message ?? "",
timedOut: e.signal === "SIGTERM",
};
}
}
export function expectBlocked(result: ExecResult): void {
// exitCode !== 0 或 stdout/stderr 包含 permission/operation not permitted 等关键字
const blocked = result.exitCode !== 0 ||
/permission|operation not permitted|denied|not allowed|read-only/i.test(result.stderr) ||
/permission|operation not permitted|denied|not allowed|read-only/i.test(result.stdout);
if (!blocked) {
throw new Error(
`Expected operation to be blocked, but it succeeded.\nExit code: ${result.exitCode}\nStdout: ${result.stdout}\nStderr: ${result.stderr}`
);
}
}
export function expectAllowed(result: ExecResult): void {
if (result.exitCode !== 0) {
throw new Error(
`Expected operation to be allowed, but it failed.\nExit code: ${result.exitCode}\nStdout: ${result.stdout}\nStderr: ${result.stderr}`
);
}
}

View File

@@ -0,0 +1,82 @@
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { spawnSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { describe, expect, it } from 'vitest';
const testFileDir = path.dirname(fileURLToPath(import.meta.url));
const projectRoot = path.resolve(testFileDir, '..', '..');
const checkerScript = path.join(projectRoot, 'scripts', 'tools', 'check-import-boundaries.js');
function writeFile(root: string, relPath: string, content: string) {
const fullPath = path.join(root, relPath);
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
fs.writeFileSync(fullPath, content, 'utf8');
}
function runChecker(tempProjectRoot: string) {
return spawnSync('node', [checkerScript], {
cwd: tempProjectRoot,
env: {
...process.env,
QIMING_BOUNDARY_PROJECT_ROOT: tempProjectRoot,
},
encoding: 'utf8',
});
}
function withTempProject(assertion: (root: string) => void) {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'qiming-boundary-'));
try {
assertion(root);
} finally {
fs.rmSync(root, { recursive: true, force: true });
}
}
describe('check-import-boundaries script', () => {
it('passes for valid main/renderer separation', () => {
withTempProject((root) => {
writeFile(root, 'src/main/bootstrap/startup.ts', 'export const start = () => 1;\n');
writeFile(root, 'src/main/main.ts', "import { start } from './bootstrap/startup';\nstart();\n");
writeFile(root, 'src/renderer/services/core/api.ts', 'export const call = () => 1;\n');
writeFile(
root,
'src/renderer/components/pages/Home.tsx',
"import { call } from '@renderer/services/core/api';\nexport const Home = () => call();\n",
);
const result = runChecker(root);
expect(result.status).toBe(0);
expect(result.stdout).toContain('Import boundary check passed.');
});
});
it('fails when renderer imports main code directly', () => {
withTempProject((root) => {
writeFile(root, 'src/main/bootstrap/startup.ts', 'export const start = () => 1;\n');
writeFile(
root,
'src/renderer/components/pages/Home.tsx',
"import { start } from '@main/bootstrap/startup';\nexport const Home = () => start();\n",
);
const result = runChecker(root);
expect(result.status).toBe(1);
expect(result.stderr).toContain('[renderer-process-boundary]');
});
});
it('fails when importing bridge files', () => {
withTempProject((root) => {
writeFile(root, 'src/main/bootstrap/startup.ts', 'export const start = () => 1;\n');
writeFile(root, 'src/main/startup.ts', "export * from './bootstrap/startup';\n");
writeFile(root, 'src/main/main.ts', "import { start } from '@/main/startup';\nstart();\n");
const result = runChecker(root);
expect(result.status).toBe(1);
expect(result.stderr).toContain('[no-bridge-imports]');
});
});
});

View File

@@ -0,0 +1,52 @@
import fs from 'node:fs';
import path from 'node:path';
import { createRequire } from 'node:module';
import { fileURLToPath } from 'node:url';
import { describe, expect, it } from 'vitest';
const testFileDir = path.dirname(fileURLToPath(import.meta.url));
const projectRootByFs = path.resolve(testFileDir, '..', '..');
const require = createRequire(import.meta.url);
const { getProjectRoot, resolveFromProject } = require(path.join(
projectRootByFs,
'scripts',
'utils',
'project-paths.js',
));
describe('scripts project path contracts', () => {
it('resolves Electron client root correctly', () => {
const root = getProjectRoot();
expect(root).toBe(projectRootByFs);
expect(fs.existsSync(path.join(root, 'package.json'))).toBe(true);
expect(fs.existsSync(path.join(root, 'scripts'))).toBe(true);
});
it('resolves resources and node_modules from project root', () => {
expect(resolveFromProject('resources')).toBe(path.join(projectRootByFs, 'resources'));
expect(resolveFromProject('node_modules')).toBe(path.join(projectRootByFs, 'node_modules'));
});
it('keeps moved scripts wired to shared project-path helper', () => {
const scripts = [
'scripts/prepare/prepare-uv.js',
'scripts/prepare/prepare-node.js',
'scripts/prepare/prepare-git.js',
'scripts/prepare/prepare-lanproxy.js',
'scripts/build/sign-uv-mac.js',
'scripts/build/dist-current-platform.js',
'scripts/tools/check-startup-ports.js',
'scripts/tools/generate-tray-icons.js',
'scripts/tools/test-integrated-node.js',
];
const legacyPattern = /path\.resolve\(__dirname,\s*'\.\.'\)/;
for (const relPath of scripts) {
const fullPath = path.join(projectRootByFs, relPath);
const content = fs.readFileSync(fullPath, 'utf8');
expect(content).toContain('project-paths');
expect(content).not.toMatch(legacyPattern);
}
});
});

View File

@@ -0,0 +1,48 @@
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";
import {
generateSandboxMatrixDocument,
renderSandboxMatrixMarkdown,
stringifySandboxMatrixJson,
} from "@main/services/sandbox/sandboxMatrix";
const testFileDir = path.dirname(fileURLToPath(import.meta.url));
const projectRoot = path.resolve(testFileDir, "..", "..");
const repoRoot = path.resolve(projectRoot, "..", "..");
const docsDir = path.join(repoRoot, "docs");
const jsonPath = path.join(docsDir, "sandbox-matrix.generated.json");
const mdPath = path.join(docsDir, "sandbox-matrix.generated.md");
function ensureDir(dir: string): void {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
}
describe("sandbox matrix artifact consistency", () => {
it("should generate deterministic matrix artifacts and keep repository baseline in sync", () => {
const doc = generateSandboxMatrixDocument();
const generatedJson = stringifySandboxMatrixJson(doc);
const generatedMd = renderSandboxMatrixMarkdown(doc);
const writeMode = process.env.SANDBOX_MATRIX_WRITE === "1";
if (writeMode) {
ensureDir(docsDir);
fs.writeFileSync(jsonPath, generatedJson, "utf8");
fs.writeFileSync(mdPath, generatedMd, "utf8");
}
expect(fs.existsSync(jsonPath)).toBe(true);
expect(fs.existsSync(mdPath)).toBe(true);
const baselineJson = fs.readFileSync(jsonPath, "utf8");
const baselineMd = fs.readFileSync(mdPath, "utf8");
expect(baselineJson).toBe(generatedJson);
expect(baselineMd).toBe(generatedMd);
});
});

View File

@@ -0,0 +1,91 @@
import path from "node:path";
import { pathToFileURL } from "node:url";
import { fileURLToPath } from "node:url";
import { beforeAll, describe, expect, it } from "vitest";
const testFileDir = path.dirname(fileURLToPath(import.meta.url));
const projectRoot = path.resolve(testFileDir, "..", "..");
const modulePath = path.join(
projectRoot,
"scripts",
"mcp",
"sandboxed-bash-security.mjs",
);
type SecurityModule = {
buildSandboxHelperEnv: (
baseEnv: Record<string, string>,
sandboxPath?: string,
) => Record<string, string>;
resolveSandboxWorkingDirectory: (
requestedCwd: string,
sandboxMode: string,
writableRoots: string[],
) => string;
};
let securityMod: SecurityModule;
beforeAll(async () => {
securityMod = (await import(pathToFileURL(modulePath).href)) as SecurityModule;
});
describe("sandboxed-bash security helpers", () => {
it("should filter sensitive env vars and keep only safe env keys", () => {
const env = securityMod.buildSandboxHelperEnv(
{
PATH: "C:\\Windows\\System32",
TEMP: "C:\\Temp",
HOME: "C:\\Users\\demo",
COMSPEC: "C:\\Windows\\System32\\cmd.exe",
PATHEXT: ".COM;.EXE;.BAT;.CMD",
SystemDrive: "C:",
ANTHROPIC_API_KEY: "secret-anthropic",
OPENAI_API_KEY: "secret-openai",
},
"",
);
expect(env.PATH).toBe("C:\\Windows\\System32");
expect(env.TEMP).toBe("C:\\Temp");
expect(env.HOME).toBe("C:\\Users\\demo");
expect(env.COMSPEC).toBe("C:\\Windows\\System32\\cmd.exe");
expect(env.PATHEXT).toBe(".COM;.EXE;.BAT;.CMD");
expect(env.SystemDrive).toBe("C:");
expect(env.ANTHROPIC_API_KEY).toBeUndefined();
expect(env.OPENAI_API_KEY).toBeUndefined();
});
it("should prepend sandbox tool path to PATH", () => {
const env = securityMod.buildSandboxHelperEnv(
{
PATH: "C:\\Windows\\System32",
},
"C:\\sandbox\\bin",
);
expect(env.PATH.startsWith("C:\\sandbox\\bin;")).toBe(true);
});
it("should fallback cwd to first writable root when outside workspace", () => {
const root = path.resolve("/workspace/project");
const outside = path.resolve("/outside/path");
const cwd = securityMod.resolveSandboxWorkingDirectory(
outside,
"workspace-write",
[root],
);
expect(cwd).toBe(root);
});
it("should keep cwd unchanged when already inside writable root", () => {
const root = path.resolve("/workspace/project");
const inside = path.resolve("/workspace/project/subdir");
const cwd = securityMod.resolveSandboxWorkingDirectory(
inside,
"workspace-write",
[root],
);
expect(cwd).toBe(inside);
});
});