import { closeVerifierResources } from "../../../scripts/lib/verifier-cleanup.mjs"; import { Client, InMemoryTransport } from "@modelcontextprotocol/client"; import { chmod, mkdir, open, readdir, writeFile } from "node:fs/promises"; import { join } from "node:path"; import { expect, onTestFinished, test, vi } from "vitest"; import * as nativeBound from "../../../src/pcap/PcapNativeBound.js"; import { PcapProvider } from "../../../src/pcap/PcapProvider.js"; import { PrivateRuntimeRoot, type PrivateRuntimeRootOptions, } from "../../../src/process/PrivateRuntimeRoot.js"; import { createServer } from "../../../src/server/createServer.js"; import { createTestBinarySession } from "../../fixtures/binarySession.js"; import { parseMcpToolError } from "../../fixtures/mcpToolError.js"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; // POSIX fixtures use real mkdtemp under caller-controlled temporary parents. const it = test.skipIf(process.platform === "win32"); const nonRoot = process.getuid?.() !== 0; const stubs = join(import.meta.dirname, "../../fixtures/pcap"); type Allocate = ( options: PrivateRuntimeRootOptions, allocate: (options: PrivateRuntimeRootOptions) => Promise, ) => Promise; /** Inspect a capture through MCP while only the pcap workspace allocation is redirected. */ const inspectWith = async (allocate: Allocate, path: string) => { const create = PrivateRuntimeRoot.create.bind(PrivateRuntimeRoot); vi.spyOn(PrivateRuntimeRoot, "create").mockImplementation((options = {}) => options.prefix === "rea-pcap-" ? allocate(options, create) : create(options), ); // macOS has no native capture bound; admit it so allocation is reached. vi.spyOn(nativeBound, "preparePcapNativeBound").mockResolvedValue({ nativeBound: {}, limitations: ["Native resource admission simulated by this test"], }); onTestFinished(() => { vi.restoreAllMocks(); }); const provider = new PcapProvider({ environment: { REA_TSHARK_COMMAND: join(stubs, "tshark-stub.sh"), REA_CAPINFOS_COMMAND: join(stubs, "capinfos-stub.sh"), }, }); const session = createTestBinarySession(() => { throw new Error("No native binary provider"); }); const server = createServer( { kind: "session", session }, { pcapAnalysis: provider }, ); const client = new Client({ name: "pcap-workspace-test", version: "1" }); const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair(); onTestFinished(() => closeVerifierResources([ () => client.close(), () => server.close(), () => provider.close(), async () => { const closed = await session.close(); if (!closed.ok) throw closed.error; }, ]), ); await server.connect(serverTransport); await client.connect(clientTransport); return parseMcpToolError( await client.callTool({ name: "inspect_pcap_capture", arguments: { path }, }), ).error; }; const systemError = (code: string, path: string) => Object.assign(new Error(`${code}: simulated, mkdtemp '${path}'`), { code, path, }); it.each([ ["ENOTDIR", "a regular file"], // Root bypasses directory permissions, so EACCES needs a non-root account. ...(nonRoot ? [["EACCES", "a mode-0500 directory"] as const] : []), ])( "reports real %s allocation under %s as an unusable workspace, not a size limit", async (code) => { const root = await createTestTempDirectory("rea-pcap-workspace-"); const parent = join(root, "parent"); if (code === "ENOTDIR") await writeFile(parent, "not a directory"); else { await mkdir(parent, { mode: 0o500 }); onTestFinished(() => chmod(parent, 0o700)); } let cause: unknown; const error = await inspectWith( (options, create) => create({ ...options, parent }).catch((failure: unknown) => { cause = failure; throw failure; }), join(root, "missing.pcap"), ); expect(cause).toMatchObject({ code }); expect(error).toMatchObject({ code: "execution_failure", category: "execution_failure", message: expect.stringContaining( `Cannot prepare the private analysis workspace (${code})`, ) as unknown, remediation: { action: expect.stringContaining("TMPDIR") as unknown, }, details: { provider_id: "pcap", operation: "inspect_pcap_capture", diagnostics: { stage: "workspace", workspace_path: null, path: code === "ENOTDIR" ? `${parent}/.` : (expect.stringContaining(join(parent, "rea-pcap-")) as unknown), system_code: code, }, }, }); expect(JSON.stringify(error)).not.toContain("file-size"); }, ); it("reaches input admission when the workspace parent is usable", async () => { const root = await createTestTempDirectory("rea-pcap-workspace-"); const error = await inspectWith( (options, create) => create({ ...options, parent: root }), join(root, "missing.pcap"), ); expect(error.code).toBe("invalid_request"); expect( (await readdir(root)).filter((name) => name.startsWith("rea-pcap-")), ).toEqual([]); }); it.each([ ["ENOSPC", "resource_constraint", "Free disk space or quota"], ["EDQUOT", "resource_constraint", "Free disk space or quota"], ["EMFILE", "execution_failure", "open-file limit"], ["ENFILE", "execution_failure", "open-file limit"], ["EROFS", "execution_failure", "TMPDIR"], ])( "classifies simulated %s allocation by its storage or descriptor cause", async (code, expected, recovery) => { const root = await createTestTempDirectory("rea-pcap-workspace-"); const template = join(root, "rea-pcap-XXXXXX"); const error = await inspectWith( () => Promise.reject(systemError(code, template)), join(root, "missing.pcap"), ); expect(error).toMatchObject({ code: expected, remediation: { action: expect.stringContaining(recovery) as unknown }, }); if (expected === "resource_constraint") expect(error.details).toMatchObject({ resource: "file-size", reported_limits: { workspace_path: null, path: template, system_code: code, }, }); else expect(error.details).toMatchObject({ diagnostics: { stage: "workspace", path: template, system_code: code }, }); }, ); test.skipIf(process.platform === "win32" || !nonRoot)( "removes a partially prepared workspace whose contents cannot be created", async () => { const root = await createTestTempDirectory("rea-pcap-workspace-"); let workspace: string | undefined; const error = await inspectWith( async (options, create) => { const allocated = await create({ ...options, parent: root }); workspace = allocated.path; // The owner-only workspace exists, but its configuration directory cannot. await chmod(allocated.path, 0o500); return allocated; }, join(root, "missing.pcap"), ); expect(error).toMatchObject({ code: "execution_failure", details: { diagnostics: { stage: "workspace", workspace_path: workspace, path: join(workspace ?? "", "configuration"), system_code: "EACCES", }, }, }); expect( (await readdir(root)).filter((name) => name.startsWith("rea-pcap-")), ).toEqual([]); }, ); it("still reports a capture over the snapshot budget as a file-size limit", async () => { const root = await createTestTempDirectory("rea-pcap-workspace-"); const capture = join(root, "oversized.pcap"); // Sparse: one byte over the 2 GiB owned-snapshot allowance, no data blocks. const handle = await open(capture, "w"); await handle.truncate(2 * 1024 ** 3 + 1); await handle.close(); const error = await inspectWith( (options, create) => create({ ...options, parent: root }), capture, ); expect(error).toMatchObject({ code: "resource_constraint", details: { resource: "file-size", reported_limits: { max_capture_bytes: 2 * 1024 ** 3 }, }, }); expect( (await readdir(root)).filter((name) => name.startsWith("rea-pcap-")), ).toEqual([]); });