Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/architecture/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Key implications:

- The provider/tool surface is the capability boundary, not the JavaScript syntax itself.
- Fresh runtimes, schema validation, JSON-only boundaries, timeouts, memory limits, and bounded logs are defense-in-depth features.
- In-process execution still shares the host process. Use a separate process, container, VM, or similar boundary when the code source is hostile or multi-tenant.
- In-process and worker-hosted execution still share the host process. Use `@execbox/remote` behind a separate process, container, VM, or similar boundary when the code source is hostile or multi-tenant.
- Wrapping third-party MCP servers is a separate dependency-trust decision from letting end users author guest code.

## Architecture In One Paragraph
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture/execbox-executors.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ If all shells are busy and the pool is already at `maxSize`, the next `acquire()

- Successful executions return the shell to the pool.
- Normal guest/runtime/tool failures also return the shell, because they do not imply a poisoned host shell.
- `timeout` and `internal_error` results evict the shell, because those outcomes mean the worker/child or transport state may no longer be trustworthy.
- `timeout` and `internal_error` results evict the shell, because those outcomes mean the worker or transport state may no longer be trustworthy.
- Idle pooled shells are evicted after `idleTimeoutMs`, down to `minSize`.
- `dispose()` tears down the executor-owned pool and any idle shells it still owns.

Expand Down
2 changes: 1 addition & 1 deletion docs/architecture/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,5 @@ Key implications:

- The provider/tool surface is the capability boundary, not the JavaScript syntax itself.
- Fresh runtimes, schema validation, JSON-only boundaries, timeouts, memory limits, and bounded logs are defense-in-depth features.
- In-process execution still shares the host process. Use a separate process, container, VM, or similar boundary when the code source is hostile or multi-tenant.
- In-process and worker-hosted execution still share the host process. Use `@execbox/remote` behind a separate process, container, VM, or similar boundary when the code source is hostile or multi-tenant.
- Wrapping third-party MCP servers is a separate dependency-trust decision from letting end users author guest code.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"package:check": "npm_config_cache=$PWD/.npm-cache CI=1 npm run build",
"test": "vitest run",
"test:dist-smoke": "node --import tsx scripts/test-dist-smoke.ts",
"test:security": "node ./node_modules/vitest/vitest.mjs run packages/core/__tests__/security/isJsonSerializable.test.ts packages/core/__tests__/core/createToolCallDispatcher.test.ts packages/core/__tests__/protocol/hostSession.test.ts packages/quickjs/__tests__/protocolEndpoint.test.ts packages/quickjs/__tests__/remoteEndpoint.test.ts && node ./node_modules/vitest/vitest.mjs run packages/core/__tests__/mcp/penetration.test.ts packages/remote/__tests__/penetration.test.ts packages/quickjs/__tests__/hostedPenetration.test.ts && node ./node_modules/vitest/vitest.mjs run packages/quickjs/__tests__/workerHostLifecycle.test.ts",
"test:security": "vitest run packages/*/__tests__/security",
"test:watch": "vitest",
"typecheck": "tsc --noEmit && node --import tsx scripts/check-workspace-entrypoints.ts"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { QuickJsExecutor } from "@execbox/quickjs";

import { runWrappedMcpPenetrationSuite } from "../../test-support/runWrappedMcpPenetrationSuite";
import { runWrappedMcpPenetrationSuite } from "../../../test-support/runWrappedMcpPenetrationSuite";

runWrappedMcpPenetrationSuite(
"QuickJS wrapped MCP penetration tests",
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/protocol/nodeBootstrap.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const SOURCE_MODE_EXEC_ARGV = ["--conditions=source", "--import", "tsx"];

/**
* Returns the extra Node flags needed to launch transport-backed child entries
* Returns the extra Node flags needed to launch transport-backed worker entries
* directly from source during local development and tests.
*/
export function getNodeTransportExecArgv(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { QuickJsExecutor } from "../src/index";
import { runWrappedMcpPenetrationSuite } from "../../core/test-support/runWrappedMcpPenetrationSuite";
import { runWrappedMcpPenetrationSuite } from "../../../core/test-support/runWrappedMcpPenetrationSuite";
import { QuickJsExecutor } from "../../src/index";

runWrappedMcpPenetrationSuite(
"QuickJsExecutor worker host wrapped MCP",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest";

import type { DispatcherMessage, RunnerMessage } from "@execbox/core/protocol";

import { attachQuickJsProtocolEndpoint } from "../src/runner/protocolEndpoint";
import { attachQuickJsProtocolEndpoint } from "../../src/runner/protocolEndpoint";

const runtimeOptions = {
maxLogChars: 64_000,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {
TransportCloseReason,
} from "@execbox/core/protocol";

import { attachQuickJsRemoteEndpoint } from "../src/remoteEndpoint";
import { attachQuickJsRemoteEndpoint } from "../../src/remoteEndpoint";

type MessageHandler = (message: DispatcherMessage) => void;
type CloseHandler = (reason?: TransportCloseReason) => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe("QuickJsExecutor worker host lifecycle", () => {
});

it("returns internal_error when the worker exits before sending a result", async () => {
const { QuickJsExecutor } = await import("../src/index");
const { QuickJsExecutor } = await import("../../src/index");
const executor = new QuickJsExecutor({ host: "worker" });

const result = await executor.execute("1 + 1", []);
Expand All @@ -54,7 +54,7 @@ describe("QuickJsExecutor worker host lifecycle", () => {
});

it("uses explicit source bootstrap conditions in repo source mode", async () => {
const { QuickJsExecutor } = await import("../src/index");
const { QuickJsExecutor } = await import("../../src/index");
const executor = new QuickJsExecutor({ host: "worker" });

await executor.execute("1 + 1", []);
Expand All @@ -71,7 +71,7 @@ describe("QuickJsExecutor worker host lifecycle", () => {
it("terminates a silent worker only once when execution times out", async () => {
vi.useFakeTimers();
state.autoExitOnStart = false;
const { QuickJsExecutor } = await import("../src/index");
const { QuickJsExecutor } = await import("../../src/index");
const executor = new QuickJsExecutor({
host: "worker",
cancelGraceMs: 0,
Expand All @@ -92,7 +92,7 @@ describe("QuickJsExecutor worker host lifecycle", () => {
});

it("does not create a worker when the caller signal is already aborted", async () => {
const { QuickJsExecutor } = await import("../src/index");
const { QuickJsExecutor } = await import("../../src/index");
const executor = new QuickJsExecutor({ host: "worker" });
const controller = new AbortController();
controller.abort();
Expand All @@ -113,7 +113,7 @@ describe("QuickJsExecutor worker host lifecycle", () => {
it("terminates a silent worker only once when the caller aborts", async () => {
vi.useFakeTimers();
state.autoExitOnStart = false;
const { QuickJsExecutor } = await import("../src/index");
const { QuickJsExecutor } = await import("../../src/index");
const executor = new QuickJsExecutor({
host: "worker",
cancelGraceMs: 0,
Expand Down
10 changes: 0 additions & 10 deletions packages/remote/__tests__/penetration.test.ts

This file was deleted.

10 changes: 10 additions & 0 deletions packages/remote/__tests__/security/penetration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { runWrappedMcpPenetrationSuite } from "../../../core/test-support/runWrappedMcpPenetrationSuite";
import { RemoteExecutor } from "../../src/index";
import { createLoopbackTransport } from "../../test-support/createLoopbackTransport";

runWrappedMcpPenetrationSuite("RemoteExecutor wrapped MCP", (options) => {
return new RemoteExecutor({
...options,
connectTransport: () => createLoopbackTransport(),
});
});
Loading