Files
gstack/test/helpers/cso-eval-oracles.ts
T
garrytan 5d032ef299 test: delete tests of dead eval code (A)
- A1: the retired Eng lexical oracle (evaluateEngSeedCoverage,
  isEngSeedDecisionAUQ), the completion-handoff detector and the retained
  corpus had no paid caller since v1.87.6; delete their 26 replay files,
  ~2.6k helper LOC and fixtures, and the dead blocks in 8 mixed files
  (live hasNativePlanTerminal / batching assertions stay).
- A2: dead viewport approvers in autoplan-artifact-permission and their 11
  replay files + fixtures; recorder/launcher cases stay.
- A3: never-wired oracles and seeders (autoplan-phase-order,
  eng-finding-fixture, ceo-paired-fixture, design-ui-scope,
  plan-skill-completion, pty-current-screen, required-reads,
  transcript-section-logger); plan-seed-submission now decodes through the
  production createPtyScreen; section manifests name their actual guard.
- A4: zero-reference helper exports, plus execGit and invokeAndObserve
  found by the reachability pass.
- 52 fixtures orphaned by the deletions; touchfile and selection-table
  entries for every deleted path.
2026-09-29 05:09:36 +00:00

103 lines
8.4 KiB
TypeScript

/** Private evaluator inputs. Never copy this module or its JSON output into producer snapshots. */
import { createHash } from 'node:crypto';
import { CORPUS_VERSION, type EvalFamily } from '../fixtures/cso-eval/materialize';
export interface OracleRequest { method: 'GET' | 'POST'; path: string; body?: string; headers?: Record<string, string> }
export interface OracleResponse { status: number; body: string; headers?: Record<string, string> }
export interface PrivateOracle {
version: string;
controls: Array<{ request: OracleRequest; response: (value: OracleResponse) => boolean }>;
attack: OracleRequest;
vulnerable: (value: OracleResponse) => boolean;
fixed: (value: OracleResponse) => boolean;
/** More than the exposed training assertion: alternative attack payloads. */
heldOut: Array<{ request: OracleRequest; fixed: (value: OracleResponse) => boolean }>;
}
const get = (params: Record<string, string>): OracleRequest => ({ method: 'GET', path: `/action?${new URLSearchParams(params)}` });
const post = (value: object): OracleRequest => ({ method: 'POST', path: '/action', body: JSON.stringify(value), headers: { 'content-type': 'application/json' } });
const contains = (status: number, expected: string) => (response: OracleResponse) => response.status === status && response.body.includes(expected);
const rejects = (status: number) => (response: OracleResponse) => response.status === status;
const jsonValue = (value: OracleResponse): any => { try { return JSON.parse(value.body); } catch { return null; } };
export function oracleFor(family: EvalFamily): PrivateOracle {
const input: Record<EvalFamily, Omit<PrivateOracle, 'version'>> = {
'sql-injection': {
controls: [{ request: get({ name: 'alice' }), response: contains(200, 'HELLO_ALICE') }],
attack: get({ name: "nobody' OR 1=1 --" }), vulnerable: contains(200, 'SECRET_ADMIN_NOTE'),
fixed: value => value.status === 200 && Array.isArray(jsonValue(value)) && jsonValue(value).length === 0,
heldOut: [{ request: get({ name: "' UNION SELECT 'ORACLE_SQL_MARKER' --" }), fixed: value => value.status === 200 && !value.body.includes('ORACLE_SQL_MARKER') }],
},
'command-injection': {
controls: [{ request: get({ name: 'Ada' }), response: value => value.status === 200 && jsonValue(value)?.output === 'Ada' }],
attack: get({ name: '"; printf CSO_COMMAND_EXECUTED; #' }), vulnerable: value => value.status === 200 && jsonValue(value)?.output === 'CSO_COMMAND_EXECUTED', fixed: rejects(400),
heldOut: [{ request: get({ name: '$(printf ORACLE_COMMAND_MARKER)' }), fixed: rejects(400) }],
},
'path-traversal': {
controls: [{ request: get({ file: 'hello.txt' }), response: contains(200, 'PUBLIC_HELLO') }],
attack: get({ file: '../private.txt' }), vulnerable: contains(200, 'PRIVATE_DOCUMENT_SECRET'), fixed: rejects(403),
heldOut: [{ request: get({ file: 'subdir/../../private.txt' }), fixed: rejects(403) }],
},
ssrf: {
controls: [{ request: get({ url: 'http://127.0.0.1:8001/public' }), response: contains(200, 'PUBLIC_STATUS') }],
attack: get({ url: 'http://127.0.0.1:8001/private' }), vulnerable: contains(200, 'INTERNAL_SERVICE_SECRET'), fixed: rejects(403),
heldOut: [{ request: get({ url: 'http://localhost:8001/private' }), fixed: rejects(403) }],
},
'object-authorization': {
controls: [{ request: get({ id: 'invoice-1' }), response: value => value.status === 200 && jsonValue(value)?.total === 12 }],
attack: get({ id: 'invoice-2' }), vulnerable: value => value.status === 200 && jsonValue(value)?.total === 9800, fixed: rejects(403),
heldOut: [{ request: get({ id: 'invoice-2', owner: 'member-1' }), fixed: rejects(403) }],
},
'tenant-isolation': {
controls: [{ request: get({ tenant: 'tenant-a' }), response: contains(200, 'OWN_TENANT_DOCUMENT') }],
attack: get({ tenant: 'tenant-b' }), vulnerable: contains(200, 'OTHER_TENANT_SECRET'),
fixed: value => value.status === 200 && value.body.includes('OWN_TENANT_DOCUMENT') && !value.body.includes('OTHER_TENANT_SECRET'),
heldOut: [{ request: get({ tenant: 'tenant-b', actor_tenant: 'tenant-b' }), fixed: value => value.status === 200 && !value.body.includes('OTHER_TENANT_SECRET') }],
},
'html-injection': {
controls: [{ request: get({ name: 'Alice' }), response: contains(200, '<main>Welcome Alice</main>') }],
attack: get({ name: '<img src=x onerror="window.CSO_XSS=1">' }), vulnerable: contains(200, '<img src=x onerror='),
fixed: value => value.status === 200 && !value.body.includes('<img') && value.body.includes('&lt;img'),
heldOut: [{ request: get({ name: '</main><svg onload="window.ORACLE_XSS=1">' }), fixed: value => value.status === 200 && !value.body.includes('<svg') && value.body.includes('&lt;svg') }],
},
'open-redirect': {
controls: [{ request: get({ next: '/account' }), response: value => value.status === 302 && jsonValue(value)?.next === '/account' && value.headers?.location === '/account' }],
attack: get({ next: 'https://attacker.invalid/collect' }), vulnerable: value => value.status === 302 && value.headers?.location === 'https://attacker.invalid/collect', fixed: rejects(400),
heldOut: [{ request: get({ next: '//attacker.invalid/collect' }), fixed: rejects(400) }, { request: get({ next: '/\\attacker.invalid/collect' }), fixed: rejects(400) }],
},
'mass-assignment': {
controls: [{ request: post({ display_name: 'Ada' }), response: value => value.status === 200 && jsonValue(value)?.display_name === 'Ada' }],
attack: post({ role: 'admin' }), vulnerable: value => value.status === 200 && jsonValue(value)?.role === 'admin', fixed: value => value.status === 200 && jsonValue(value)?.role === 'member',
heldOut: [{ request: post({ id: 'member-2', role: 'owner', display_name: 'Grace' }), fixed: value => value.status === 200 && jsonValue(value)?.id === 'member-1' && jsonValue(value)?.role === 'member' && jsonValue(value)?.display_name === 'Grace' }],
},
'resource-exhaustion': {
controls: [{ request: get({ count: '5' }), response: value => value.status === 200 && jsonValue(value)?.count === 5 }],
// Bounded proof of missing admission, not an attempt to exhaust the runner.
attack: get({ count: '250' }), vulnerable: value => value.status === 200 && jsonValue(value)?.count === 250, fixed: rejects(400),
heldOut: [{ request: get({ count: '101' }), fixed: rejects(400) }, { request: get({ count: '0' }), fixed: rejects(400) }],
},
};
return { version: CORPUS_VERSION, ...input[family] };
}
export interface Observation { request: OracleRequest; response: OracleResponse }
export interface PrivateEvidence {
original: { booted: boolean; controls: Observation[]; attack: Observation };
patched: { booted: boolean; controls: Observation[]; attack: Observation; heldOut: Observation[]; existingTestsPassed: boolean };
immutableVerifier: boolean;
independentRootCauseReview: boolean;
featurePreserved: boolean;
boundaryMocks: boolean;
}
const sameRequest = (left: OracleRequest, right: OracleRequest) => JSON.stringify(left) === JSON.stringify(right);
/** Only trusted runner observations may enter this function; producer claims are not observations. */
export function judgeRepair(family: EvalFamily, evidence: PrivateEvidence): { reproduced: boolean; correctRepair: boolean; evidenceHash: string } {
const oracle = oracleFor(family);
const controls = (observations: Observation[]) => oracle.controls.every(control => observations.some(observation => sameRequest(control.request, observation.request) && control.response(observation.response)));
const original = evidence.original, patched = evidence.patched;
const reproduced = original.booted && controls(original.controls) && sameRequest(original.attack.request, oracle.attack) && oracle.vulnerable(original.attack.response);
const correctRepair = reproduced && patched.booted && controls(patched.controls) && sameRequest(patched.attack.request, oracle.attack) && oracle.fixed(patched.attack.response)
&& oracle.heldOut.every(assertion => patched.heldOut.some(observation => sameRequest(assertion.request, observation.request) && assertion.fixed(observation.response)))
&& patched.existingTestsPassed && evidence.immutableVerifier && evidence.independentRootCauseReview && evidence.featurePreserved && !evidence.boundaryMocks;
return { reproduced, correctRepair, evidenceHash: createHash('sha256').update(JSON.stringify({ version: oracle.version, family, evidence })).digest('hex') };
}