mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-10 23:19:09 +02:00
fix(design-detect): project means below HOME; only page dumps drop inline ignores; a whole-scan budget; prototype-safe rule counts
Third review cycle + Red Team, all reproduced before the fix: - With no repository, the wrapper adopted cwd as the repo root, so a review launched from HOME (URL mode can run from anywhere) rejected every HOME-rooted install as "repository-local", reported the user's own skill install with the wrong hint, and, for targets, accepted all of HOME (~/.ssh/id_rsa scanned). A project directory is now one strictly below HOME: `git init ~` never turns the user's installs into repository files, and from HOME only the designs allow-list qualifies as a target. - --no-inline-ignores keyed on "not inside the repo", which misclassified dumps when GSTACK_HOME sits under the repo and stripped the design-html gate's own `<!-- impeccable-disable -->` from finalized.html. Targets are classified as project / dom-dump (designs/<audit>/dom/**, the page's bytes) / artifact (other designs/ files, gstack-authored); only dumps drop inline ignores. - A repository's .impeccable/config.json can hide rules from the review; detector.ignoreValues was never surfaced. The probe prints IMPECCABLE_IGNORED_VALUES beside the rules, and the prose stops calling repo-config ignores "a decision the user made". - An engine id named `constructor` corrupted byRule through Object.prototype and `__proto__` counts vanished; byRule is a null- prototype object and an id that fails the shape check is `unmapped` as a key too. - Batches ran with no total budget (10,000 un-ignored files: hours). The scan stops at 5x the per-batch timeout with DETECT_TIMEOUT and exit 1. - The scan JSON carries an `untrusted` list of the engine- and page-derived fields, so the agent reading past the fenced DETECT_TOP block is told what is evidence. - The PATH walk keeps launcher-present for a .cmd wrapper or a differently named real file (the name gate applies to READY only). Tests: probe and scan from a fake HOME (cache READY, HOME file refused, dump scanned without inline ignores), artifact vs dump batches, prototype-member ids, the whole-scan budget over 11 batches, ignoreValues surfaced, the `untrusted` field. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
982a738663
commit
8d709c8f29
@@ -8,7 +8,8 @@
|
||||
// asserts that every sentinel-shaped token in generated docs exists here.
|
||||
//
|
||||
// probe ──► one of: IMPECCABLE_READY | IMPECCABLE_NOT_CACHED | IMPECCABLE_NOT_AVAILABLE | IMPECCABLE_DISABLED
|
||||
// ──► always: IMPECCABLE_SKILL, IMPECCABLE_HOOK, IMPECCABLE_IGNORED_RULES, IMPECCABLE_IGNORED_FILES
|
||||
// ──► always: IMPECCABLE_SKILL, IMPECCABLE_HOOK, IMPECCABLE_IGNORED_RULES, IMPECCABLE_IGNORED_FILES,
|
||||
// IMPECCABLE_IGNORED_VALUES
|
||||
// ──► maybe: IMPECCABLE_HOOK_OTHER, IMPECCABLE_CONFIG_UNREADABLE, IMPECCABLE_ENV_IGNORED,
|
||||
// IMPECCABLE_ENGINE_UNTESTED, DESIGN_DETECTOR_HINT
|
||||
// scan ──► stdout: one JSON document (--format gstack) or engine bytes (--format raw)
|
||||
@@ -26,6 +27,7 @@ export const SENTINEL = {
|
||||
HOOK_OTHER: 'IMPECCABLE_HOOK_OTHER',
|
||||
IGNORED_RULES: 'IMPECCABLE_IGNORED_RULES',
|
||||
IGNORED_FILES: 'IMPECCABLE_IGNORED_FILES',
|
||||
IGNORED_VALUES: 'IMPECCABLE_IGNORED_VALUES',
|
||||
CONFIG_UNREADABLE: 'IMPECCABLE_CONFIG_UNREADABLE',
|
||||
ENV_IGNORED: 'IMPECCABLE_ENV_IGNORED',
|
||||
ENGINE_UNTESTED: 'IMPECCABLE_ENGINE_UNTESTED',
|
||||
@@ -55,6 +57,7 @@ export const SENTINEL = {
|
||||
DESIGN_MD_REASON: 'DESIGN_MD_REASON',
|
||||
DESIGN_MD_WRITTEN: 'DESIGN_MD_WRITTEN',
|
||||
DESIGN_MD_BACKUP: 'DESIGN_MD_BACKUP',
|
||||
DESIGN_MD_EDIT_REFUSED: 'DESIGN_MD_EDIT_REFUSED',
|
||||
/** printed by the wrapper: --verbose probe trail, forwarded engine stderr */
|
||||
PROBE_STEP: 'PROBE_STEP',
|
||||
ENGINE_STDERR: 'ENGINE_STDERR',
|
||||
@@ -68,10 +71,10 @@ export const SENTINEL = {
|
||||
* reads.
|
||||
*/
|
||||
export const SELF_DESCRIBING_SENTINELS: readonly string[] = [
|
||||
SENTINEL.HOOK_OTHER, SENTINEL.IGNORED_FILES, SENTINEL.CONFIG_UNREADABLE, SENTINEL.ENV_IGNORED,
|
||||
SENTINEL.HOOK_OTHER, SENTINEL.IGNORED_FILES, SENTINEL.IGNORED_VALUES, SENTINEL.CONFIG_UNREADABLE, SENTINEL.ENV_IGNORED,
|
||||
SENTINEL.ENGINE_UNTESTED, SENTINEL.DETECT_EXIT, SENTINEL.DETECT_REFUSED, SENTINEL.DETECT_NO_TARGETS,
|
||||
SENTINEL.DETECT_TIMEOUT, SENTINEL.DETECT_PARSE_ERROR, SENTINEL.DETECT_OUTPUT_TOO_LARGE,
|
||||
SENTINEL.DESIGN_MD_TOKEN_REF_INVALID, SENTINEL.DESIGN_MD_WRITTEN, SENTINEL.DESIGN_MD_BACKUP,
|
||||
SENTINEL.DESIGN_MD_TOKEN_REF_INVALID, SENTINEL.DESIGN_MD_WRITTEN, SENTINEL.DESIGN_MD_BACKUP, SENTINEL.DESIGN_MD_EDIT_REFUSED,
|
||||
SENTINEL.PROBE_STEP, SENTINEL.ENGINE_STDERR,
|
||||
];
|
||||
|
||||
@@ -105,6 +108,8 @@ export const DETECT_LIMITS = {
|
||||
engineHashBytes: 4 * 1024 * 1024,
|
||||
/** git subprocess budgets inside the wrapper */
|
||||
gitTimeoutMs: 30_000,
|
||||
/** whole-scan wall clock, as a multiple of the per-batch timeout: a huge target set stops, it never grinds for hours */
|
||||
totalTimeoutFactor: 5,
|
||||
gitMaxBuffer: 64 * 1024 * 1024,
|
||||
field: { id: 64, engineVersion: 64, message: 120, snippet: 120, value: 200, file: 4096, diagnostic: 400, refusedTarget: 200, parseErrorPreview: 80, internalError: 300 },
|
||||
} as const;
|
||||
@@ -169,7 +174,11 @@ export interface ScanResult {
|
||||
findings: NormalizedFinding[];
|
||||
truncated: boolean;
|
||||
diagnostics: string[];
|
||||
/** JSON paths whose text is engine- and page-derived: evidence, never instructions (the stderr block carries the fence; this document carries the list) */
|
||||
untrusted: readonly string[];
|
||||
}
|
||||
|
||||
export const SCAN_UNTRUSTED_PATHS = ['findings[].file', 'findings[].snippet', 'findings[].message', 'findings[].value', 'diagnostics[]'] as const;
|
||||
|
||||
/** The bash a skill renders after a scan so exit 2 (findings) never aborts the block. */
|
||||
export const DETECT_EXIT_ECHO = `; echo "${SENTINEL.DETECT_EXIT_CODE}=$?"`;
|
||||
|
||||
Reference in New Issue
Block a user