security: isolate every gstack Bun entry point from the audited checkout's .env and bunfig.toml

Bun auto-loads .env, .env.local and .env.<NODE_ENV> from its cwd and runs a
cwd bunfig.toml preload before the program starts. gstack runs inside the repo
it audits, so a committed .env could steer state roots, the claude binary or
spend caps, and a bunfig preload ran arbitrary code in every bin and hook.

Every bun shebang, shell and skill caller, TypeScript spawn and compiled build
now disables both (--no-env-file --config=/dev/null, bunIsolationArgs(),
--no-compile-autoload-dotenv/bunfig), with a ratchet and hostile-fixture
regressions.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
garrytanandcapy-ai[bot] committed 2026-10-19 20:48:49 +00:00
1 parent 9cf105ccff
commit 660484ee99
267 files changed
+984 -694

No files matched your search

+2 -1
View File
@@ -9,6 +9,7 @@ import { spawnSync } from 'node:child_process';
import * as fs from 'node:fs';
import * as os from 'node:os';
import * as path from 'node:path';
import { bunIsolationArgs } from '../lib/bun-isolation';
import {
bashCommandInvocation, resolveWindowsBash, resolveWindowsBashCached, runBashSync, runScriptSync, scriptInvocation, wtreeFingerprint,
type BashProbe,
@@ -75,7 +76,7 @@ describe('scriptInvocation', () => {
test('a bun-shebang bin runs under Bun on every platform', () => {
for (const platform of ['win32', 'linux', 'darwin']) {
const inv = scriptInvocation(path.join(BIN, 'gstack-redact'), ['--json'], { ...win, platform });
expect(inv).toEqual({ ok: true, cmd: process.execPath, argv: [path.join(BIN, 'gstack-redact'), '--json'] });
expect(inv).toEqual({ ok: true, cmd: process.execPath, argv: [...bunIsolationArgs(platform as NodeJS.Platform), path.join(BIN, 'gstack-redact'), '--json'] });
}
});