mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-10 15:09:00 +02:00
fix: pre-landing review fixes for the v2 port wave
Review army (checklist + 5 specialists) + coverage/plan audits on the assembled branch. Genuine correctness/security/hygiene fixes: - test-paid-shards: strictTestExitCode now receives expectedFiles on the real bun path, so a shard that runs fewer files than planned (harness crash, nothing loaded) with exit 0 is no longer recorded 'passed' — the invisible-non-execution class the runner exists to kill. Pinned by the new test/strict-output.test.ts (also covers the chunk-boundary classifier). - test-paid-shards: EVALS_TIER env is validated (gate|periodic) like the --tier flag, so a typo can't self-skip every test and exit 0 green. - package.json: test:periodic:sharded sets EVALS_ALL=1, restoring the full-tier semantics the pre-shard script had (CI already set it; local eval:bg:periodic silently under-measured without it). - brain-sync.test: run() pins HOME to the temp home so gstack-artifacts-init stops writing/clobbering the operator's real ~/.gstack-artifacts-remote.txt every free-suite run; afterEach now also scrubs the current filename. - egress-receipt: cap each receipt field at 512B so a serialized line always fits the 4KB tail-read window — a longer line would make the next append hash a truncated prior line and verifyLedger report a permanent false TAMPER. warnLedgerSize short-circuits before statSync once fired (append hot path). - gstack-egress: import.meta.dir (Windows-safe) instead of new URL().pathname so grants doesn't silently report defaults on Windows; strip control chars from ledger-derived fields on render so a crafted receipt can't spoof the auditor's view. - extension/background.js + CLAUDE.md: renumber the identity-pin migration refs v1.62 -> v1.63 (main claimed 1.62.0.0; this wave queue-advances). - egress-receipt-wiring: pin lib/context-bill.ts unconditionally (both land together now); drop the dead RunShardsOptions.tier field. All fix-affected test files green; gate failures triaged as external-env (codex/gemini CLI drift) or pre-existing (hermetic-canary fails identically on base). Deferred polish tracked in the PR body + decision store. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
ea7ba921ce
commit
ccb91c3afb
+24
-3
@@ -25,7 +25,23 @@ import {
|
||||
verifyLedger,
|
||||
} from '../lib/egress-receipt';
|
||||
|
||||
const BIN_DIR = path.dirname(new URL(import.meta.url).pathname);
|
||||
// import.meta.dir is Windows-safe; new URL(import.meta.url).pathname yields
|
||||
// '/C:/...' with percent-encoded spaces there, which would make the
|
||||
// gstack-config spawn silently fail and grants report every default. Matches
|
||||
// the sibling bin/*.ts convention.
|
||||
const BIN_DIR = import.meta.dir;
|
||||
|
||||
/**
|
||||
* Strip control characters (incl. ANSI escapes) from ledger-derived strings
|
||||
* before printing. A receipt's host/payloadClass can derive from semi-trusted
|
||||
* input (a URL argument, a git remote); JSON.parse restores \u001b escapes to
|
||||
* live ESC bytes, so an attacker-shaped receipt could hide or spoof rows in
|
||||
* the very output an auditor reads. The hash chain is unaffected; this only
|
||||
* sanitizes the human render.
|
||||
*/
|
||||
function sanitizeForDisplay(value: unknown): string {
|
||||
return String(value).replace(/[\u0000-\u001F\u007F]/g, '');
|
||||
}
|
||||
|
||||
function usage(message: string): never {
|
||||
process.stderr.write(`gstack-egress: ${message}\n`);
|
||||
@@ -76,9 +92,14 @@ function egressList(args: string[], home: string): number {
|
||||
return 0;
|
||||
}
|
||||
for (const r of receipts) {
|
||||
// sink/host/payload_class/consent can carry semi-trusted content — strip
|
||||
// control chars so a crafted receipt can't spoof the auditor's view. ts,
|
||||
// bytes, and sha256 are format-constrained at write time.
|
||||
process.stdout.write(
|
||||
`${r.ts} ${r.sink} -> ${r.host} ${r.payload_class} ${r.bytes}B ` +
|
||||
`sha256=${r.sha256 ?? '(subprocess-owned)'} consent=${r.consent} status=${r.status ?? '-'}\n`,
|
||||
`${r.ts} ${sanitizeForDisplay(r.sink)} -> ${sanitizeForDisplay(r.host)} ` +
|
||||
`${sanitizeForDisplay(r.payload_class)} ${r.bytes}B ` +
|
||||
`sha256=${r.sha256 ?? '(subprocess-owned)'} consent=${sanitizeForDisplay(r.consent)} ` +
|
||||
`status=${r.status ? sanitizeForDisplay(r.status) : '-'}\n`,
|
||||
);
|
||||
}
|
||||
process.stdout.write(`${receipts.length} receipt(s) ledger: ${egressLedgerPath(home)}\n`);
|
||||
|
||||
Reference in New Issue
Block a user