From a1f021ff4a3c11fddfd9d051feebece459fd7341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Thu, 16 Apr 2026 21:48:10 -0400 Subject: [PATCH] fix(worker): invert connector bypass default and gate on packaged build (S-01) Previously `AGENTCOMPANY_ALLOW_UNSAFE_CONNECTOR_BYPASS !== "false"` meant packaged builds defaulted to passing `dangerouslyBypassApprovalsAndSandbox`, `dangerouslySkipPermissions`, `yolo`, and `--sandbox danger-full-access` to CLI connectors, bypassing ApprovalService entirely. Require both explicit opt-in (`AGENTCOMPANY_ALLOW_UNSAFE_CONNECTOR_BYPASS=true`) and a non-packaged build. Packaged builds hard-refuse regardless of the env var. Main process forks the worker with `AGENTCOMPANY_PACKAGED=` so the worker has an authoritative packaged signal. --- src/main/worker-service.ts | 8 +++++++- src/main/worker/worker-entry.ts | 9 ++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/worker-service.ts b/src/main/worker-service.ts index 46f37553..e54a2aeb 100644 --- a/src/main/worker-service.ts +++ b/src/main/worker-service.ts @@ -1,4 +1,4 @@ -import { utilityProcess } from "electron"; +import { app, utilityProcess } from "electron"; import { workerMessageSchema, type WorkerServiceDependencies } from "./worker/worker-types"; import { handleWorkerExit } from "./worker/worker-crash-recovery"; import { handleWorkerMessage } from "./worker/worker-message-handler"; @@ -37,9 +37,15 @@ export function createWorkerService({ } function createWorker() { + // S-01: Propagate packaged-build signal so the worker can hard-refuse + // connector bypass flags in production. worker = utilityProcess.fork(workerPath, [], { stdio: "pipe", serviceName: "AgentCompany Orchestrator", + env: { + ...process.env, + AGENTCOMPANY_PACKAGED: app.isPackaged ? "true" : "false", + }, }); worker.stdout?.on("data", (chunk) => { diff --git a/src/main/worker/worker-entry.ts b/src/main/worker/worker-entry.ts index 9beb4378..446c5fdd 100644 --- a/src/main/worker/worker-entry.ts +++ b/src/main/worker/worker-entry.ts @@ -80,10 +80,13 @@ const activeByAgent = new Map(); const activeByWorkspace = new Map(); const queue: RunJob[] = []; const cancelledRuns = new Set(); -// Agent runs are autonomous by design — they must execute commands without interactive approval. -// The env-var gate is retained as an emergency kill switch but defaults to enabled. +// S-01: Bypass is opt-in only. Packaged builds hard-refuse the dangerous CLI +// flags unless the operator sets BOTH `AGENTCOMPANY_ALLOW_UNSAFE_CONNECTOR_BYPASS=true` +// AND is running a dev/E2E build (AGENTCOMPANY_PACKAGED !== "true"). Main forks +// the worker with AGENTCOMPANY_PACKAGED=. +const isPackaged = process.env.AGENTCOMPANY_PACKAGED === "true"; const allowUnsafeConnectorBypass = - process.env.AGENTCOMPANY_ALLOW_UNSAFE_CONNECTOR_BYPASS !== "false"; + !isPackaged && process.env.AGENTCOMPANY_ALLOW_UNSAFE_CONNECTOR_BYPASS === "true"; function post(message: ChildMessage) { parentPort.postMessage(message);