mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-19 11:22:21 +02:00
fix(design-detect): never execute a repository-controlled engine; allow-list --changed targets; sanitize engine text
Pre-landing review findings (security + checklist), all reproduced before the fix:
- A checked-out branch could commit `.claude/skills/impeccable/scripts/bin/<os>-<arch>/impeccable`
and the probe would report READY and `scan` would run it, with the agent's full
environment. Launchers and sibling engines under the repo or cwd now count as
"skill present" only (IMPECCABLE_NOT_CACHED: repository-local install, and the
hint never names a repository-local launcher to run); only HOME-rooted installs,
IMPECCABLE_BIN, the cache, and PATH entries outside the repo qualify, all by
realpath. The engine now sees a minimal environment (PATH, HOME, TMPDIR, locale,
IMPECCABLE_*), never the agent's tokens.
- `scan --changed <base>` pushed git-derived paths without the allow-list, so a
committed symlink with a frontend extension handed a file outside the repo to
the engine. Derived targets now go through the same allow-list as explicit ones
and symlinks named by git are refused outright.
- A repo-controlled `scripts/VERSION` with embedded newlines forged probe lines;
the version is trusted only when it is semver, and every printed version is
sanitized. Engine text containing the untrusted-content fence or a
`SENTINEL:` prefix is neutralized with a zero-width space
(neutralizeSentinels in the contract), so page text cannot close the envelope
or forge a probe line.
- A failing `git diff <base>...HEAD` (unknown or unfetched base) was swallowed
and read as "no frontend changes"; it is now DETECT_REFUSED with exit 1.
- The scan allow-list root follows `${GSTACK_HOME:-$HOME/.gstack}` like the
templates and gstack-slug (config.yaml keeps gstack-config's STATE_ROOT
precedence); a quoted or commented design_detector value reads correctly.
Smaller: raw engine chunks are kept only in --format raw; diagnostics are
capped (200 kept, 20 echoed); the engine identity hash reads size + 4 MB, not
the whole binary; PROBE_STEP and ENGINE_STDERR are contract sentinels; the
--verbose gate covers every probe step; analytics use one sentinel vocabulary;
bare limits live in DETECT_LIMITS. The fake engine's knobs are IMPECCABLE_FAKE_*
(so they pass the minimal env) and a shared test helper installs it. New tests
cover each item above plus clean runs, `{}` parse errors, missing paths, and the
50 MB stdout cap.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
9a03aa5e4a
commit
60758c5ddf
@@ -12,6 +12,7 @@ import { spawnSync } from 'child_process';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import { installFakeImpeccable } from './helpers/fake-impeccable';
|
||||
|
||||
const evalCollector = createEvalCollector('e2e-review');
|
||||
|
||||
@@ -215,9 +216,7 @@ describeIfSelected('Review design lite E2E', ['review-design-lite'], () => {
|
||||
);
|
||||
fs.copyFileSync(path.join(ROOT, 'review', 'greptile-triage.md'), path.join(designDir, 'review-greptile-triage.md'));
|
||||
// Fake impeccable engine OUTSIDE the repo (the wrapper ignores an in-repo IMPECCABLE_BIN).
|
||||
fakeEngineDir = fs.mkdtempSync(path.join(os.tmpdir(), 'skill-e2e-fake-impeccable-'));
|
||||
fs.copyFileSync(path.join(ROOT, 'test', 'fixtures', 'fake-impeccable.ts'), path.join(fakeEngineDir, 'impeccable'));
|
||||
fs.chmodSync(path.join(fakeEngineDir, 'impeccable'), 0o755);
|
||||
fakeEngineDir = installFakeImpeccable('skill-e2e-fake-impeccable-').dir;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
@@ -246,7 +245,7 @@ Important: The design checklist should catch issues like blacklisted fonts, smal
|
||||
runId,
|
||||
env: {
|
||||
IMPECCABLE_BIN: path.join(fakeEngineDir, 'impeccable'),
|
||||
FAKE_IMPECCABLE_OUTPUT: path.join(ROOT, 'test', 'fixtures', 'impeccable-detect-sample.json'),
|
||||
IMPECCABLE_FAKE_OUTPUT: path.join(ROOT, 'test', 'fixtures', 'impeccable-detect-sample.json'),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user