From f7188bc78bebc7b6d0634cb291fabddf7e0d5d7f Mon Sep 17 00:00:00 2001 From: Khaliq Date: Mon, 24 Aug 2026 23:47:48 +0200 Subject: [PATCH 1/3] fix(mount): create the detached initial-sync script mode 0600 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The detached initial-sync launcher wrote its generated script with a plain `cat >`, so the file landed at the process umask default — 0644 under a 022 umask — and the default token ingress rendered the path-scoped credential into it as a `--token` literal. Any other process able to read the file could recover a reusable credential, and the script outlived the sync that used it. - Create the script inside `(umask 077 && cat > ...)` so the mode is constrained at creation; a chmod after the write would leave a readable window. Verify the mode that actually landed (`stat -c %a`, falling back to `stat -f %Lp`) and refuse to launch if it is not 600. - Add `tokenIngress: 'creds-file'`, which renders no credential literal at all and relies on the mode-0600 creds file already supplied alongside the launch command. It is opt-in rather than implied by `credsFilePath`, because pre-creds binaries ignore the creds-file env var and would fail authentication silently if `--token` were dropped from under them. - Remove the generated script once the detached sync exits, before the exit sentinel is written, so a poller that has observed completion cannot race back and read it. The log, pid and exit sentinels are kept as non-secret failure diagnostics. The tests execute the real launcher through /bin/sh under an explicit 022 umask and assert against the file that lands on disk; a string assertion on the generated shell would not have caught the umask defect. Behaviour verified on dash, bash --posix and zsh. Refs AgentWorkforce/sandbox#30 Co-Authored-By: Claude Opus 5 Session-Id: 798d531e-b682-47ba-90dc-0a26290aa6e6 Session-Id: b4b52699-ca5c-4331-b702-8989d1e91983 Session-Id: b4b52699-ca5c-4331-b702-8989d1e91983 Session-Id: b4b52699-ca5c-4331-b702-8989d1e91983 Session-Id: b4b52699-ca5c-4331-b702-8989d1e91983 --- src/mount-script.test.ts | 285 +++++++++++++++++++++++++++++++++++++++ src/mount-script.ts | 74 ++++++++-- 2 files changed, 346 insertions(+), 13 deletions(-) diff --git a/src/mount-script.test.ts b/src/mount-script.test.ts index 3ba0385..c027b1f 100644 --- a/src/mount-script.test.ts +++ b/src/mount-script.test.ts @@ -7,6 +7,7 @@ import { mkdtempSync, readFileSync, rmSync, + statSync, writeFileSync, } from "node:fs"; import { tmpdir } from "node:os"; @@ -17,8 +18,13 @@ import { buildRelayfileMountStartShell, buildRelayfileMountFlushShell, buildRelayfileMountInitialSyncShell, + buildRelayfileMountInitialSyncBackgroundShell, buildRelayfileMountPathArgsShell, buildRelayfileMountShellTemplate, + RELAYFILE_INITIAL_SYNC_EXIT_PATH, + RELAYFILE_INITIAL_SYNC_LOG_PATH, + RELAYFILE_INITIAL_SYNC_PID_PATH, + RELAYFILE_INITIAL_SYNC_SCRIPT_PATH, } from "./mount-script.js"; const TOKEN = "relay_pa_thisisasecrettoken_do_not_leak"; @@ -712,3 +718,282 @@ describe("initial-sync idle watchdog progress files", () => { ); }); }); + +/** + * Regression guard for AgentWorkforce/sandbox#30. + * + * The detached initial-sync launcher generates a shell script under /tmp and + * hands it to a background process. Two things went wrong at once: + * + * - `cat >