mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-16 09:55:29 +02:00
v1.87.0.0 feat: add verified CSO audits and replayable repair bundles (#2852)
* feat(cso): add verified audits and replayable repair bundles * fix(cso): harden qualification and setup boundaries * fix(cso): assemble security canaries at runtime * fix(cso): bound release proof and maintenance work Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix(cso): require complete evaluation reports Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix(cso): replay expired snapshots from supplied source Co-Authored-By: OpenAI Codex <noreply@openai.com> * test(cso): synchronize DNS cancellation assertion Co-Authored-By: OpenAI Codex <noreply@openai.com> * chore(ship): exempt repository owner from liveness proof Co-Authored-By: OpenAI Codex <noreply@openai.com> * test(cso): make recheck retention overlap deterministic Co-Authored-By: OpenAI Codex <noreply@openai.com> * chore: bump version and changelog (v1.85.0.0) Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix(cso): pass native release gates Co-Authored-By: OpenAI Codex <noreply@openai.com> * chore: move release to v1.86.0.0 Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix(cso): resolve rechecks by finding Co-Authored-By: OpenAI Codex <noreply@openai.com> * chore: move release to v1.87.0.0 Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix(cso): pass macOS and Windows release gates Normalize BSD wc output, compare Windows paths by filesystem identity, preserve portable snapshot race coverage, and narrow POSIX-only Windows fixtures. Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix(cso): harden native verification gates * fix(cso): refine Windows native diagnostics * test(cso): isolate Windows Git startup failure * test(cso): stabilize Windows native diagnostics * fix(cso): support hardened Git on Windows * fix(cso): close final verification gaps * test(cso): bound cold Docker fixture setup * fix(cso): restore cross-platform free-suite gates --------- Co-authored-by: OpenAI Codex <noreply@openai.com>
This commit is contained in:
co-authored by
OpenAI Codex
parent
9f81911136
commit
4a3c6a8a3c
@@ -0,0 +1,118 @@
|
||||
import { afterAll, beforeAll, describe, expect, test } from 'bun:test';
|
||||
import * as fs from 'node:fs';import * as os from 'node:os';import * as path from 'node:path';import { spawnSync } from 'node:child_process';
|
||||
import { createHash } from 'node:crypto';
|
||||
import { fingerprint, sha256 } from '../lib/cso/contracts';
|
||||
import { patchHash } from '../lib/cso/verification';
|
||||
import { redact } from '../lib/cso/process';
|
||||
const ROOT=path.resolve(import.meta.dir,'..'),launcher=path.join(ROOT,'bin',process.platform==='win32'?'gstack-cso-launcher.exe':'gstack-cso-launcher');let root='',repo='',state='';
|
||||
const CREDENTIAL_CANARY=['ghp_','abcdefghijklmnopqrstuvwxyz1234567890'].join('');
|
||||
function command(args:string[],extra:Record<string,string>={},file=launcher){const r=spawnSync(file,args,{cwd:repo,encoding:'utf8',env:{HOME:root,GSTACK_HOME:state,PATH:`${repo}/hostile-bin:/usr/bin:/bin`,BUN_OPTIONS:`--preload=${repo}/preload.ts`,BUN_BE_BUN:'1',NODE_OPTIONS:`--require=${repo}/preload.cjs`,RUBYOPT:`-r${repo}/preload.rb`,PYTHONPATH:repo,LD_PRELOAD:path.join(repo,'missing.so'),BASH_ENV:path.join(repo,'bashenv'),...extra},timeout:30_000});return r;}
|
||||
function git(...args:string[]){const r=spawnSync('/usr/bin/git',['-C',repo,...args],{encoding:'utf8',env:{HOME:root,PATH:'/usr/bin:/bin'},timeout:30_000});if(r.status)throw new Error(r.stderr);return r.stdout;}
|
||||
beforeAll(()=>{root=fs.mkdtempSync(path.join(os.tmpdir(),'cso-cli-'));repo=path.join(root,'repo');state=path.join(root,'state');fs.mkdirSync(repo);git('init','-q');git('config','user.email','fixture@example.test');git('config','user.name','Fixture');fs.mkdirSync(path.join(repo,'src'));fs.writeFileSync(path.join(repo,'src','users.ts'),'export const tenantQuery = (id:string) => db.user.findUnique({where:{id}})\n');fs.writeFileSync(path.join(repo,'src','control.test.ts'),'export const control = true\n');fs.writeFileSync(path.join(repo,'.env'),`TOKEN=${CREDENTIAL_CANARY}\n`);git('add','src/users.ts','src/control.test.ts','.env');git('commit','-qm','fixture');fs.mkdirSync(path.join(repo,'hostile-bin'));for(const tool of ['git','dirname'])fs.writeFileSync(path.join(repo,'hostile-bin',tool),`#!/bin/sh\ntouch '${path.join(repo,'path-shim-ran')}'\nexit 99\n`,{mode:0o755});for(const f of ['preload.ts','preload.cjs','preload.rb','bashenv'])fs.writeFileSync(path.join(repo,f),`require('fs').writeFileSync('${path.join(repo,'autoload-ran')}','yes')\n`);});
|
||||
afterAll(()=>fs.rmSync(root,{recursive:true,force:true}));
|
||||
|
||||
describe('compiled CSO command workflow',()=>{
|
||||
test('trusted launcher resists runtime autoload variables and repository PATH shims',()=>{const r=command(['--version']);expect(r.status).toBe(0);expect(JSON.parse(r.stdout)).toEqual({version:'3.0.0',abi:3});expect(fs.existsSync(path.join(repo,'autoload-ran'))).toBe(false);expect(fs.existsSync(path.join(repo,'path-shim-ran'))).toBe(false);});
|
||||
test('trusted launcher resolves relative caller paths without trusting an inherited cwd override',()=>{const hostile=path.join(root,'missing-caller-cwd'),diagnosed=command(['doctor','--repo','.'],{GSTACK_CSO_CALLER_CWD:hostile,DOCKER_HOST:'tcp://127.0.0.1:2375'});expect(diagnosed.status).toBe(0);expect(JSON.parse(diagnosed.stdout).checks.find((item:any)=>item.capability==='static-snapshot')).toMatchObject({status:'ready'});const started=command(['start','--repo','.','--scope','auth','--offline'],{GSTACK_CSO_CALLER_CWD:hostile});expect(started.status).toBe(0);const run=JSON.parse(started.stdout),input=path.join(repo,'relative-submission.json');try{fs.writeFileSync(input,'{}');expect(command(['submit',run.runId,'relative-submission.json'],{GSTACK_CSO_CALLER_CWD:hostile}).status).toBe(0);}finally{fs.rmSync(input,{force:true});}});
|
||||
test.skipIf(process.platform!=='linux')('static launcher prevents loader injection before environment scrubbing',()=>{const source=path.join(root,'preload.c'),library=path.join(root,'preload.so'),marker=path.join(root,'loader-ran');fs.writeFileSync(source,'#include <fcntl.h>\n#include <stdlib.h>\n#include <unistd.h>\n__attribute__((constructor)) static void mark(void){const char*p=getenv("CSO_PRELOAD_MARKER");if(p){int f=open(p,O_WRONLY|O_CREAT,0600);if(f>=0)close(f);}}\n');const built=spawnSync('/usr/bin/cc',['-shared','-fPIC',source,'-o',library],{encoding:'utf8',timeout:30_000});expect(built.status).toBe(0);const r=command(['--version'],{LD_PRELOAD:library,CSO_PRELOAD_MARKER:marker});expect(r.status).toBe(0);expect(fs.existsSync(marker)).toBe(false);});
|
||||
test('package-manager launcher symlinks resolve the trusted sibling core',()=>{const npmBin=path.join(root,'npm-bin');fs.mkdirSync(npmBin,{recursive:true});const link=path.join(npmBin,'gstack-cso');fs.symlinkSync(launcher,link);const r=command(['--version'],{},link);expect(r.status).toBe(0);expect(JSON.parse(r.stdout)).toEqual({version:'3.0.0',abi:3});});
|
||||
test.skipIf(process.platform==='win32')('compiled core starts in the canonical trusted launcher directory',()=>{const install=path.join(root,'trusted launcher'),hostile=path.join(repo,'hostile cwd');fs.mkdirSync(install);fs.mkdirSync(hostile);const publicLauncher=path.join(install,'gstack-cso-launcher'),fixtureCore=path.join(install,'gstack-cso-core'),source=path.join(root,'cwd-fixture.c');fs.writeFileSync(source,'#include <stdio.h>\n#include <unistd.h>\n#include <limits.h>\nint main(void){char cwd[PATH_MAX];if(!getcwd(cwd,sizeof cwd))return 2;puts(cwd);return 0;}\n');const built=spawnSync('/usr/bin/cc',[source,'-o',fixtureCore],{encoding:'utf8',timeout:30_000});expect(built.status).toBe(0);const digest=createHash('sha256').update(fs.readFileSync(fixtureCore)).digest('hex'),launcherBuild=spawnSync('/usr/bin/cc',['-std=c11','-D_POSIX_C_SOURCE=200809L','-O2',`-DGSTACK_CSO_CORE_SHA256=\"${digest}\"`,path.join(ROOT,'lib/cso/launcher.c'),'-o',publicLauncher],{encoding:'utf8',timeout:30_000});expect(launcherBuild.status).toBe(0);fs.writeFileSync(path.join(install,'.gstack-cso-generation'),`${digest}\n`);const r=spawnSync(publicLauncher,[],{cwd:hostile,encoding:'utf8',env:{...process.env,HOME:root,GSTACK_HOME:state},timeout:30_000});expect(r.status).toBe(0);expect(r.stdout.trim()).toBe(fs.realpathSync(install));expect(r.stdout.trim()).not.toBe(fs.realpathSync(hostile));});
|
||||
test('schema advertises only caller-owned verification input',()=>{const r=command(['schema']);expect(r.status).toBe(0);const schema=JSON.parse(r.stdout);expect(schema.verification).not.toHaveProperty('result');expect(schema.helperOwned).toContain('repair result and label');});
|
||||
test('v2 imports remain readable and immutable without upgrading legacy proof',()=>{
|
||||
const source=path.join(root,'legacy-v2.json'),legacy={schemaVersion:2,findings:[{status:'VERIFIED',title:'Historical authorization finding',description:`Captured credential ${CREDENTIAL_CANARY}`,fingerprint:'legacy-fingerprint',location:{path:'src/legacy.ts',line:17,symbol:'legacyAuthorization'},impact:'Cross-tenant disclosure',recommendation:'Bind the lookup to the authenticated tenant',repair:'VERIFIED'}]};
|
||||
fs.writeFileSync(source,JSON.stringify(legacy));
|
||||
const imported=command(['import-v2',source]);expect(imported.status).toBe(0);expect(imported.stdout+imported.stderr).not.toContain(CREDENTIAL_CANARY);const result=JSON.parse(imported.stdout),finding=result.report.findings[0];
|
||||
expect(result.id).toMatch(/^[a-f0-9]{64}$/);expect(result.warning).toContain('does not establish reproduction, tested repair, or closure');expect(result.report).toMatchObject({schemaVersion:2,readOnly:true});
|
||||
expect(finding).toMatchObject({status:'VERIFIED',evidence:'legacy_review',reproduction:'not_attempted',repair:'not_attempted',closure:'unknown',legacy:{fingerprint:'legacy-fingerprint',location:{path:'src/legacy.ts',line:17,symbol:'legacyAuthorization'},impact:'Cross-tenant disclosure',recommendation:'Bind the lookup to the authenticated tenant',repair:'VERIFIED'}});
|
||||
fs.writeFileSync(source,JSON.stringify({schemaVersion:2,findings:[]}));
|
||||
const inspected=command(['inspect-v2',result.id]);expect(inspected.status).toBe(0);expect(inspected.stdout+inspected.stderr).not.toContain(CREDENTIAL_CANARY);expect(JSON.parse(inspected.stdout)).toEqual({id:result.id,report:result.report});
|
||||
const stored=path.join(state,'security','cso','legacy-imports',`${result.id}.json`);expect(fs.existsSync(stored)).toBe(true);expect(fs.readFileSync(stored,'utf8')).not.toContain(CREDENTIAL_CANARY);
|
||||
const invalid=command(['inspect-v2','../legacy-v2.json']);expect(invalid.status).not.toBe(0);expect(invalid.stderr).toContain('64-character import ID');
|
||||
const missing=command(['inspect-v2','0'.repeat(64)]);expect(missing.status).not.toBe(0);expect(missing.stderr).toContain('MISSING_INPUT');
|
||||
const beforeUnsafe=fs.readdirSync(path.dirname(stored)).length,unsafeKey=`severity\u202eHIGH`;fs.writeFileSync(source,JSON.stringify({schemaVersion:2,findings:[{status:'OPEN',title:'unsafe',nested:{[unsafeKey]:'forged'}}]}));const unsafe=command(['import-v2',source]);expect(unsafe.status).not.toBe(0);expect(unsafe.stderr).toContain('unsafe property');expect(unsafe.stdout+unsafe.stderr).not.toContain(unsafeKey);expect(fs.readdirSync(path.dirname(stored))).toHaveLength(beforeUnsafe);
|
||||
const changed=JSON.parse(fs.readFileSync(stored,'utf8'));changed.findings[0].status='CHANGED';fs.writeFileSync(stored,JSON.stringify(changed,null,2)+'\n');const tampered=command(['inspect-v2',result.id]);expect(tampered.status).not.toBe(0);expect(tampered.stderr).toContain('identity is inconsistent');
|
||||
});
|
||||
test('wallet-shaped source paths remain addressable through stable opaque handles',()=>{
|
||||
const walletRepo=path.join(root,'wallet-path-repo'),wallet='0x1234567890abcdef1234567890abcdef12345678',sourcePath=`src/${wallet}.ts`;
|
||||
fs.mkdirSync(path.join(walletRepo,'src'),{recursive:true});
|
||||
const runGit=(...args:string[])=>{const result=spawnSync('/usr/bin/git',['-C',walletRepo,...args],{encoding:'utf8',env:{HOME:root,PATH:'/usr/bin:/bin'},timeout:30_000});if(result.status)throw new Error(result.stderr);};
|
||||
runGit('init','-q');runGit('config','user.email','fixture@example.test');runGit('config','user.name','Fixture');
|
||||
fs.writeFileSync(path.join(walletRepo,sourcePath),`export const value = true\n// TOKEN=${CREDENTIAL_CANARY}\n`);fs.writeFileSync(path.join(walletRepo,'control.test.js'),'test(\"control\",()=>{})\n');runGit('add','.');runGit('commit','-qm','wallet-shaped path');
|
||||
const started=command(['start','--repo',walletRepo,'--comprehensive','--offline']);expect(started.status).toBe(0);
|
||||
const run=JSON.parse(started.stdout),dir=path.join(state,'security','cso',run.repoId,run.runId),privateManifest=JSON.parse(fs.readFileSync(path.join(dir,'snapshot.json'),'utf8'));
|
||||
const privateEntry=privateManifest.entries.find((item:any)=>item.path===sourcePath);expect(privateEntry.path).toBe(sourcePath);expect(privateEntry.pathId).toMatch(/^[a-f0-9]{32}$/);
|
||||
const inspected=command(['inspect',run.runId]);expect(inspected.status).toBe(0);const view=JSON.parse(inspected.stdout),entry=view.manifest.entries.find((item:any)=>item.displayPath);
|
||||
expect(JSON.stringify(view)).not.toContain(wallet);expect(JSON.stringify(view)).not.toContain('ghp_');expect(entry.path).toMatch(/^@cso-path\/\/[a-f0-9]{32}$/);expect(entry.displayPath).toContain('<REDACTED-pii.wallet>');expect(entry).not.toHaveProperty('pathId');expect(view.sensitiveEvidence.find((item:any)=>item.path===entry.path)).toBeDefined();
|
||||
const read=command(['read',run.runId,entry.path]);expect(read.status).toBe(0);expect(read.stdout).toContain('export const value = true');
|
||||
const history=command(['history',run.runId,entry.path]);expect(history.status).toBe(0);expect(history.stdout).toContain('<REDACTED-pii.wallet>');expect(history.stdout).toContain('export const value = true');expect(history.stdout).not.toContain('No retained patch hunks');expect(history.stdout).not.toContain(wallet);
|
||||
const input=path.join(root,`wallet-path-${run.runId}.json`),finding={title:'Sensitive-shaped source path',rootCause:'Public route omits an authorization predicate',location:{path:entry.path,line:1,symbol:'value'},advisoryIds:[],severity:'high',confidence:'high',confidenceRationale:'A caller-to-sink trace establishes the missing predicate',evidence:'supported',attackerControl:'Caller chooses the identifier',impact:'Unauthorized record disclosure',scenario:'A caller requests another tenant record',trace:['route','value','response'],references:[`${entry.displayPath}:1`],recommendation:'Bind access to the authenticated tenant',challenge:{reviewer:'reviewer-session',independent:true,mode:'independent_agent',callers:'route caller checked',controls:'authorization is absent',counterevidence:'none found',conclusion:'the tenant predicate is absent'}};
|
||||
fs.writeFileSync(input,JSON.stringify({findings:[finding]}));const submitted=command(['submit',run.runId,input]);expect(submitted.status).toBe(0);
|
||||
const report=JSON.parse(fs.readFileSync(path.join(dir,'report.json'),'utf8'));expect(report.findings).toHaveLength(1);expect(report.findings[0].location.path).toBe(entry.path);expect(report.findings[0].id).toBe(fingerprint(report.findings[0]));expect(JSON.stringify(report)).not.toContain(wallet);
|
||||
const before=fs.readFileSync(path.join(dir,'snapshot',sourcePath),'utf8'),request:any={findingId:report.findings[0].id,runtimeProfile:'node-v1',port:3456,start:{executable:'/usr/local/bin/node',args:['app.js']},legitimate:[{name:'control',path:'/health',method:'GET',expected:{status:200}}],security:{name:'authorization',path:'/records/other',method:'GET',expected:{status:403},vulnerable:{status:200}},existingTests:[{executable:'/usr/local/bin/node',args:['--test']}],testFiles:['control.test.js'],fixtures:{},boundaryFiles:[entry.path],changes:[{path:entry.path,beforeSha256:sha256(before),after:'export const value = false\n',effect:'source'}],review:{reviewer:'reviewer-session',independent:true,rootCauseRepaired:true,featurePreserved:true,boundaryMocks:false,rationale:'The authorization decision replaces the vulnerable behavior while preserving the control',reviewedPatchHash:''}};request.review.reviewedPatchHash=patchHash(request);fs.writeFileSync(input,JSON.stringify(request));const reviewed=command(['record-review',run.runId,input,'--producer','producer-session']);expect(reviewed.status).toBe(0);request.review.artifactId=JSON.parse(reviewed.stdout).reviewArtifactId;fs.writeFileSync(input,JSON.stringify(request));const verified=command(['verify',run.runId,input]);expect(verified.status).not.toBe(0);expect(verified.stderr).toContain('PREREQUISITE');expect(verified.stderr).not.toContain('Boundary files');expect(verified.stderr).not.toContain('contained relative path');
|
||||
expect(report.coverage.find((item:any)=>item.domain==='snapshot-inputs')).toMatchObject({status:'assessed',gaps:[]});
|
||||
},15_000);
|
||||
test('daily audits expose staged tracked deletions as replay-stable handles and material gaps',()=>{
|
||||
const deletedRepo=path.join(root,'deleted-path-repo'),wallet='0xabcdefabcdefabcdefabcdefabcdefabcdefabcd',sourcePath=`src/${wallet}.ts`;
|
||||
fs.mkdirSync(path.join(deletedRepo,'src'),{recursive:true});
|
||||
const runGit=(...args:string[])=>{const result=spawnSync('/usr/bin/git',['-C',deletedRepo,...args],{encoding:'utf8',env:{HOME:root,PATH:'/usr/bin:/bin'},timeout:30_000});if(result.status)throw new Error(result.stderr);return result.stdout;};
|
||||
runGit('init','-q');runGit('config','user.email','fixture@example.test');runGit('config','user.name','Fixture');fs.writeFileSync(path.join(deletedRepo,sourcePath),'export const authorization = true\n');fs.writeFileSync(path.join(deletedRepo,'app.js'),'export const app = true\n');runGit('add','.');runGit('commit','-qm','tracked authorization source');runGit('rm','-q',sourcePath);
|
||||
const started=command(['start','--repo',deletedRepo,'--scope','auth','--offline']);expect(started.status).toBe(0);const run=JSON.parse(started.stdout),dir=path.join(state,'security','cso',run.repoId,run.runId),privateManifest=JSON.parse(fs.readFileSync(path.join(dir,'snapshot.json'),'utf8'));
|
||||
expect(privateManifest.entries.some((item:any)=>item.path===sourcePath)).toBe(false);expect(privateManifest.deletedPaths).toHaveLength(1);expect(privateManifest.deletedPaths[0]).toMatchObject({path:sourcePath});expect(privateManifest.deletedPaths[0].pathId).toMatch(/^[a-f0-9]{32}$/);
|
||||
const inspected=command(['inspect',run.runId]);expect(inspected.status).toBe(0);const view=JSON.parse(inspected.stdout),deleted=view.manifest.deletedPaths[0],coverage=view.report.coverage.find((item:any)=>item.domain==='snapshot-inputs');
|
||||
expect(JSON.stringify(view)).not.toContain(wallet);expect(deleted.path).toMatch(/^@cso-path\/\/[a-f0-9]{32}$/);expect(deleted.displayPath).toContain('<REDACTED-pii.wallet>');expect(deleted).not.toHaveProperty('pathId');expect(coverage.status).toBe('partial');expect(coverage.gaps).toEqual([`${deleted.path}: tracked source is deleted from the worktree; only retained history is available for assessment`]);expect(view.report.source.transformations).toContainEqual({path:deleted.path,handling:'tracked source deleted; retained history only'});
|
||||
const history=command(['history',run.runId,deleted.path]);expect(history.status).toBe(0);expect(history.stdout).toContain('<REDACTED-pii.wallet>');expect(history.stdout).not.toContain(wallet);const read=command(['read',run.runId,deleted.path]);expect(read.status).not.toBe(0);expect(read.stderr).toContain('outside the retained inventory');
|
||||
const tampered=structuredClone(privateManifest);delete tampered.deletedPaths;fs.writeFileSync(path.join(dir,'snapshot.json'),JSON.stringify(tampered,null,2)+'\n');const rejected=command(['inspect',run.runId]);expect(rejected.status).not.toBe(0);expect(rejected.stderr).toContain('Snapshot original identity is inconsistent');
|
||||
});
|
||||
test('runtime plans encode sensitive canonical test argv with snapshot handles',()=>{
|
||||
const planRepo=path.join(root,'sensitive-plan-repo'),wallet='0x1111111111111111111111111111111111111112',testPath=`${wallet}.test.js`;fs.mkdirSync(planRepo);
|
||||
const runGit=(...args:string[])=>{const result=spawnSync('/usr/bin/git',['-C',planRepo,...args],{encoding:'utf8',env:{HOME:root,PATH:'/usr/bin:/bin'},timeout:30_000});if(result.status)throw new Error(result.stderr);};
|
||||
runGit('init','-q');runGit('config','user.email','fixture@example.test');runGit('config','user.name','Fixture');fs.writeFileSync(path.join(planRepo,'package.json'),JSON.stringify({name:'sensitive-plan',version:'1.0.0',scripts:{start:'node app.js',test:'node --test'}}));fs.writeFileSync(path.join(planRepo,'package-lock.json'),JSON.stringify({name:'sensitive-plan',version:'1.0.0',lockfileVersion:3,packages:{'':{name:'sensitive-plan',version:'1.0.0'}}}));fs.writeFileSync(path.join(planRepo,'app.js'),'export const app = true\n');fs.writeFileSync(path.join(planRepo,testPath),'const test=require("node:test");test("control",()=>{})\n');runGit('add','.');runGit('commit','-qm','sensitive test path');
|
||||
const started=command(['start','--repo',planRepo,'--comprehensive','--offline']);expect(started.status).toBe(0);const run=JSON.parse(started.stdout),planned=command(['runtime-plan',run.runId,'node','--port','3456']);expect(planned.status).toBe(0);const plan=JSON.parse(planned.stdout),serialized=JSON.stringify(plan);
|
||||
expect(serialized).not.toContain(wallet);const testHandle=plan.tests.files.find((value:string)=>value.startsWith('@cso-path//'));expect(testHandle).toMatch(/^@cso-path\/\/[a-f0-9]{32}$/);expect(plan.tests.commands[0].args).toContain(`./${testHandle}`);expect(plan.start.command).toEqual({executable:'/usr/local/bin/node',args:['app.js']});
|
||||
});
|
||||
test('wallet-shaped helper finding IDs survive submit, review, and verification admission',()=>{const started=command(['start','--repo',repo,'--comprehensive','--offline']);expect(started.status).toBe(0);const run=JSON.parse(started.stdout),base:any={title:'Wallet-shaped helper ID',rootCause:'Tenant query omits caller tenant predicate 0',location:{path:'src/users.ts',line:1,symbol:'tenantQuery'},advisoryIds:[],severity:'high',confidence:'high',confidenceRationale:'Caller-to-sink trace directly establishes the missing predicate',evidence:'supported',attackerControl:'Tenant chooses the record ID',impact:'Cross-tenant record disclosure',scenario:'A tenant requests another tenant record by ID',trace:['route','tenantQuery','database'],references:['src/users.ts:1'],recommendation:'Bind the query to the authenticated tenant',challenge:{reviewer:'reviewer-session',independent:true,mode:'independent_agent',callers:'route caller checked',controls:'authentication lacks authorization',counterevidence:'none found',conclusion:'tenant predicate is absent'}};let helperId='';for(let i=0;i<10_000;i++){base.rootCause=`Tenant query omits caller tenant predicate ${i}`;helperId=fingerprint(base);if(redact(helperId)!==helperId)break;}expect(redact(helperId)).not.toBe(helperId);const input=path.join(root,`wallet-id-${run.runId}.json`);fs.writeFileSync(input,JSON.stringify({findings:[base]}));expect(command(['submit',run.runId,input]).status).toBe(0);const reportPath=path.join(state,'security','cso',run.repoId,run.runId,'report.json'),stored=JSON.parse(fs.readFileSync(reportPath,'utf8'));expect(stored.findings[0].id).toBe(helperId);const before=fs.readFileSync(path.join(repo,'src','users.ts'),'utf8'),request:any={findingId:helperId,runtimeProfile:'node-v1',port:3456,start:{executable:'/usr/local/bin/node',args:['src/users.ts']},legitimate:[{name:'control',path:'/health',method:'GET',expected:{status:200}}],security:{name:'tenant boundary',path:'/users/other',method:'GET',expected:{status:403},vulnerable:{status:200}},existingTests:[{executable:'/usr/local/bin/node',args:['--test']}],testFiles:['src/control.test.ts'],fixtures:{},boundaryFiles:['src/users.ts'],changes:[{path:'src/users.ts',beforeSha256:sha256(before),after:before+'// tenant predicate\n',effect:'source'}],review:{reviewer:'reviewer-session',independent:true,rootCauseRepaired:true,featurePreserved:true,boundaryMocks:false,rationale:'The tenant predicate is added while the control remains intact',reviewedPatchHash:''}};request.review.reviewedPatchHash=patchHash(request);fs.writeFileSync(input,JSON.stringify(request));const reviewed=command(['record-review',run.runId,input,'--producer','producer-session']);expect(reviewed.status).toBe(0);request.review.artifactId=JSON.parse(reviewed.stdout).reviewArtifactId;fs.writeFileSync(input,JSON.stringify(request));const verified=command(['verify',run.runId,input]);expect(verified.status).not.toBe(0);expect(verified.stderr).toContain('PREREQUISITE');expect(verified.stderr).not.toContain('REDACTION_FAILED');const review=JSON.parse(fs.readFileSync(path.join(path.dirname(reportPath),'reviews',`${request.review.artifactId}.json`),'utf8'));expect(review.findingId).toBe(helperId);});
|
||||
test('daily find, early submit, and finish persist a truthful report without changing source',()=>{const before=git('status','--porcelain=v1','-z'),started=command(['start','--repo',repo,'--scope','auth','--offline']);expect(started.status).toBe(0);const run=JSON.parse(started.stdout),runId=run.runId;expect(run.completeness).toBe('not assessed');const reportPath=path.join(state,'security','cso',run.repoId,runId,'report.json');expect(fs.existsSync(reportPath)).toBe(true);const current=JSON.parse(fs.readFileSync(reportPath,'utf8'));
|
||||
const wallet='0x1234567890abcdef1234567890abcdef12345678',submission={application:{actors:['authenticated tenant user'],assets:['tenant records'],entrypoints:['GET /users/:id'],tenantBoundaries:['record.tenant_id equals session.tenant_id'],sensitiveOperations:['read tenant record'],invariants:['a tenant cannot read another tenant record']},findings:[{title:'Cross-tenant user read',rootCause:`Tenant query ${wallet} omits caller tenant predicate`,location:{path:'src/users.ts',line:1,symbol:'tenantQuery'},advisoryIds:[],severity:'high',confidence:'high',confidenceRationale:'The captured caller-to-sink trace and control review directly support the finding',evidence:'supported',attackerControl:'Authenticated caller chooses the record ID',impact:'Another tenant record is returned',scenario:'A tenant supplies a known record ID owned by another tenant and receives that record',trace:['GET /users/:id','tenantQuery','findUnique by id'],references:['src/users.ts:1','OWASP API1:2023'],recommendation:'Bind the lookup predicate to the authenticated tenant identifier before returning the record',challenge:{reviewer:'independent-2',independent:true,mode:'independent_agent',callers:'Authenticated route forwards path ID',controls:'Authentication exists; authorization predicate does not',counterevidence:'Opaque IDs reduce guessing but do not authorize',conclusion:'The caller can provide a known cross-tenant ID'}}],coverage:current.coverage.filter((c:any)=>!['snapshot-inputs','history-inputs'].includes(c.domain)).map((c:any)=>({...c,status:'assessed',method:'caller and middleware trace',gaps:[],evidence:[`${c.domain} inspected against captured source`]})),gaps:[]};const file=path.join(root,'submission.json');fs.writeFileSync(file,JSON.stringify(submission));const submitted=command(['submit',runId,file]);expect(submitted.status).toBe(0);expect(JSON.parse(fs.readFileSync(reportPath,'utf8')).findings).toHaveLength(1);const finished=command(['finish',runId]);expect(finished.status).toBe(0);const final=JSON.parse(fs.readFileSync(reportPath,'utf8'));expect(final.completeness).toBe('complete');expect(final.findings[0]).toMatchObject({reproduction:'not_attempted',repair:'not_attempted',closure:'open'});expect(final.findings[0].id).toBe(fingerprint(final.findings[0]));expect(JSON.stringify(final)).not.toContain(wallet);const markdown=fs.readFileSync(path.join(path.dirname(reportPath),'report.md'),'utf8');expect(markdown.startsWith('complete — domain:auth')).toBe(true);expect(markdown).toContain('.env: excluded: credential or execution configuration');expect(markdown).not.toContain('ghp_');expect(git('status','--porcelain=v1','-z')).toBe(before);});
|
||||
test('credential originals are withheld rather than printed',()=>{const run=JSON.parse(command(['start','--repo',repo,'--scope','auth','--offline']).stdout);const result=command(['read',run.runId,'.env']);expect(result.status).not.toBe(0);expect(result.stderr).toContain('MISSING_INPUT');expect(result.stdout+result.stderr).not.toContain('ghp_');});
|
||||
test('bounded submission and snapshot readers reject multiply-linked pathnames',()=>{const run=JSON.parse(command(['start','--repo',repo,'--scope','auth','--offline']).stdout),dir=path.join(state,'security','cso',run.repoId,run.runId),inputSource=path.join(root,`linked-input-source-${run.runId}.json`),input=path.join(root,`linked-input-${run.runId}.json`);fs.writeFileSync(inputSource,'{}');fs.linkSync(inputSource,input);const submitted=command(['submit',run.runId,input]);expect(submitted.status).not.toBe(0);expect(submitted.stderr).toContain('one bounded regular file');const readable=path.join(dir,'readable','src','users.ts'),outside=path.join(root,`linked-readable-${run.runId}`);fs.linkSync(readable,outside);const read=command(['read',run.runId,'src/users.ts']);expect(read.status).not.toBe(0);expect(read.stderr).toContain('one bounded regular file');});
|
||||
test.skipIf(process.platform==='win32')('rejects a SARIF FIFO without blocking on open',()=>{const run=JSON.parse(command(['start','--repo',repo,'--scope','auth','--offline']).stdout),fifo=path.join(root,`sarif-${run.runId}.pipe`);expect(spawnSync('/usr/bin/mkfifo',[fifo],{encoding:'utf8',timeout:5_000}).status).toBe(0);const started=Date.now(),imported=command(['import-sarif',run.runId,fifo]);expect(Date.now()-started).toBeLessThan(2_000);expect(imported.status).not.toBe(0);expect(imported.stderr).toContain('bounded regular file');});
|
||||
test('model submissions cannot overwrite helper-owned readiness or scanner coverage',()=>{const run=JSON.parse(command(['start','--repo',repo,'--scope','auth','--offline']).stdout),file=path.join(root,'helper-coverage.json');fs.writeFileSync(file,JSON.stringify({coverage:[{domain:'runtime-readiness',scope:'node',status:'assessed',method:'claimed by model',gaps:[],exclusions:[],evidence:['untrusted claim']}]}));const result=command(['submit',run.runId,file]);expect(result.status).not.toBe(0);expect(result.stderr).toContain('helper-owned');const report=JSON.parse(fs.readFileSync(path.join(state,'security','cso',run.repoId,run.runId,'report.json'),'utf8'));expect(report.coverage.some((x:any)=>x.domain==='runtime-readiness')).toBe(false);});
|
||||
test('submission typos are rejected instead of silently weakening evidence',()=>{const run=JSON.parse(command(['start','--repo',repo,'--scope','auth','--offline']).stdout),file=path.join(root,'typo-submission.json');for(const value of [{finding:[]},{modelUsage:{source:'host',tokens:1,tokenz:1}},{application:{actors:['a'],assets:['b'],entrypoints:['c'],tenantBoundaries:['d'],sensitiveOperations:['e'],invariants:['f'],unknown:['g']}}]){fs.writeFileSync(file,JSON.stringify(value));const result=command(['submit',run.runId,file]);expect(result.status).not.toBe(0);expect(result.stderr).toContain('Unexpected');}});
|
||||
test('submission collections and numeric usage fail with precise schema errors',()=>{const run=JSON.parse(command(['start','--repo',repo,'--scope','auth','--offline']).stdout),file=path.join(root,'invalid-submission-shape.json');for(const [body,message] of [['{"findings":{}}','submission.findings must be an array'],['{"coverage":{}}','submission.coverage must be an array'],['{"modelUsage":{"source":"host","tokens":0,"cost":1e400}}','finite nonnegative']]){fs.writeFileSync(file,body);const result=command(['submit',run.runId,file]);expect(result.status).not.toBe(0);expect(result.stderr).toContain(message);}});
|
||||
test('the reserved reporting minute accepts evidence until the actual deadline',()=>{const run=JSON.parse(command(['start','--repo',repo,'--scope','auth','--offline']).stdout),reportPath=path.join(state,'security','cso',run.repoId,run.runId,'report.json'),report=JSON.parse(fs.readFileSync(reportPath,'utf8')),file=path.join(root,`reporting-reserve-${run.runId}.json`);fs.writeFileSync(file,'{}');report.deadline=new Date(Date.now()+30_000).toISOString();fs.writeFileSync(reportPath,JSON.stringify(report,null,2)+'\n');expect(command(['submit',run.runId,file]).status).toBe(0);report.deadline=new Date(Date.now()-1_000).toISOString();fs.writeFileSync(reportPath,JSON.stringify(report,null,2)+'\n');const expired=command(['submit',run.runId,file]);expect(expired.status).not.toBe(0);expect(expired.stderr).toContain('Audit deadline reached');});
|
||||
test('explicit base pins history even when finding scope is not diff-only',()=>{const head=git('rev-parse','HEAD').trim(),started=command(['start','--repo',repo,'--scope','auth','--offline','--base','HEAD']);expect(started.status).toBe(0);const run=JSON.parse(started.stdout),dir=path.join(state,'security','cso',run.repoId,run.runId),report=JSON.parse(fs.readFileSync(path.join(dir,'report.json'),'utf8')),history=JSON.parse(fs.readFileSync(path.join(dir,'history-status.json'),'utf8'));expect(report.policy.diff).toBe(false);expect(report.source.baseCommit).toBe(head);expect(history.range).toBe(`${head}..${head}`);const invalid=command(['start','--repo',repo,'--scope','auth','--offline','--base','missing-ref']);expect(invalid.status).not.toBe(0);expect(invalid.stderr).toContain('MISSING_INPUT');});
|
||||
test('an optional scanner prerequisite does not turn completed manual coverage partial',()=>{
|
||||
const run=JSON.parse(command(['start','--repo',repo,'--scope','auth','--offline']).stdout);
|
||||
const scanned=command(['scan',run.runId,'gitleaks']);expect(scanned.status).toBe(0);expect(JSON.parse(scanned.stdout).status).toBe('not_assessed');
|
||||
const reportPath=path.join(state,'security','cso',run.repoId,run.runId,'report.json'),report=JSON.parse(fs.readFileSync(reportPath,'utf8'));
|
||||
const input=path.join(root,`manual-${run.runId}.json`);fs.writeFileSync(input,JSON.stringify({application:{actors:['tenant user'],assets:['tenant records'],entrypoints:['GET /users/:id'],tenantBoundaries:['tenant id'],sensitiveOperations:['record read'],invariants:['tenant isolation']},coverage:report.coverage.filter((c:any)=>!c.domain.startsWith('scanner:')&&!['snapshot-inputs','history-inputs'].includes(c.domain)).map((c:any)=>({...c,status:'assessed',method:'manual source and caller review',gaps:[],evidence:['fresh captured-source trace']})),gaps:[]}));
|
||||
expect(command(['submit',run.runId,input]).status).toBe(0);expect(command(['finish',run.runId]).status).toBe(0);const final=JSON.parse(fs.readFileSync(reportPath,'utf8'));expect(final.completeness).toBe('complete');expect(final.coverage.find((c:any)=>c.domain==='scanner:gitleaks').status).toBe('not_assessed');
|
||||
});
|
||||
test('unread tracked source is a disclosed helper-owned material gap',()=>{
|
||||
const binaryRepo=path.join(root,'binary-repo'),runGit=(...args:string[])=>{const result=spawnSync('/usr/bin/git',['-C',binaryRepo,...args],{encoding:'utf8',env:{HOME:root,PATH:'/usr/bin:/bin'},timeout:30_000});if(result.status)throw new Error(result.stderr);};
|
||||
fs.mkdirSync(binaryRepo);runGit('init','-q');runGit('config','user.email','fixture@example.test');runGit('config','user.name','Fixture');
|
||||
fs.writeFileSync(path.join(binaryRepo,'app.js'),'export const ready = true\n');fs.writeFileSync(path.join(binaryRepo,'auth.wasm'),Buffer.from([0,97,115,109,1,0,0,0]));
|
||||
runGit('add','app.js','auth.wasm');runGit('commit','-qm','binary security boundary');
|
||||
const started=command(['start','--repo',binaryRepo,'--scope','auth','--offline']);expect(started.status).toBe(0);
|
||||
const run=JSON.parse(started.stdout),reportPath=path.join(state,'security','cso',run.repoId,run.runId,'report.json'),initial=JSON.parse(fs.readFileSync(reportPath,'utf8'));
|
||||
expect(initial.coverage.find((item:any)=>item.domain==='snapshot-inputs')).toMatchObject({status:'partial',gaps:['auth.wasm: in-scope source payload was unread and withheld from static and runtime assessment']});
|
||||
expect(initial.source.transformations).toContainEqual({path:'auth.wasm',handling:'withheld: binary or redaction failed'});
|
||||
const override=path.join(root,`snapshot-override-${run.runId}.json`);fs.writeFileSync(override,JSON.stringify({coverage:[{domain:'snapshot-inputs',scope:'domain:auth',status:'assessed',method:'model claim',gaps:[],exclusions:[],evidence:['claimed complete']}]}));
|
||||
const rejected=command(['submit',run.runId,override]);expect(rejected.status).not.toBe(0);expect(rejected.stderr).toContain('helper-owned');
|
||||
const evidence=path.join(root,`binary-evidence-${run.runId}.json`);fs.writeFileSync(evidence,JSON.stringify({application:{actors:['authenticated user'],assets:['authorization policy'],entrypoints:['application request'],tenantBoundaries:['authorization boundary'],sensitiveOperations:['protected operation'],invariants:['authorization is enforced']},coverage:initial.coverage.filter((item:any)=>!['snapshot-inputs','history-inputs'].includes(item.domain)).map((item:any)=>({...item,status:'assessed',method:'captured source review',gaps:[],evidence:['reviewed readable captured source']})),gaps:[]}));
|
||||
expect(command(['submit',run.runId,evidence]).status).toBe(0);expect(command(['finish',run.runId]).status).toBe(0);
|
||||
const final=JSON.parse(fs.readFileSync(reportPath,'utf8')),markdown=fs.readFileSync(path.join(path.dirname(reportPath),'report.md'),'utf8');
|
||||
expect(final.completeness).toBe('partial');expect(final.coverage.find((item:any)=>item.domain==='snapshot-inputs').status).toBe('partial');
|
||||
expect(markdown.startsWith('partial — domain:auth')).toBe(true);expect(markdown).toContain('auth.wasm: in-scope source payload was unread');expect(markdown).toContain('auth.wasm: withheld: binary or redaction failed');
|
||||
});
|
||||
test('a surviving root-cause variant leaves the fresh recheck open for correction',()=>{const original=JSON.parse(command(['start','--repo',repo,'--scope','auth','--offline']).stdout),rootCause='Tenant query omits caller tenant predicate',finding={title:'Cross-tenant user read',rootCause,location:{path:'src/users.ts',line:1,symbol:'tenantQuery'},advisoryIds:[],severity:'high',confidence:'high',confidenceRationale:'The captured caller-to-sink trace and control review directly support the finding',evidence:'supported',attackerControl:'Authenticated caller chooses the record ID',impact:'Another tenant record is returned',scenario:'A tenant supplies a known record ID owned by another tenant and receives that record',trace:['GET /users/:id','tenantQuery','findUnique by id'],references:['src/users.ts:1','OWASP API1:2023'],recommendation:'Bind the lookup predicate to the authenticated tenant identifier before returning the record',challenge:{reviewer:'independent-2',independent:true,mode:'independent_agent',callers:'Authenticated route forwards path ID',controls:'Authentication exists; authorization predicate does not',counterevidence:'Opaque IDs reduce guessing but do not authorize',conclusion:'The caller can provide a known cross-tenant ID'}},application={actors:['tenant user'],assets:['records'],entrypoints:['GET /users/:id'],tenantBoundaries:['tenant id'],sensitiveOperations:['record read'],invariants:['tenant isolation']},reportPath=path.join(state,'security','cso',original.repoId,original.runId,'report.json'),report=JSON.parse(fs.readFileSync(reportPath,'utf8')),submission=path.join(root,'recheck-original.json');fs.writeFileSync(submission,JSON.stringify({application,findings:[finding],coverage:report.coverage.filter((c:any)=>!['snapshot-inputs','history-inputs'].includes(c.domain)).map((c:any)=>({...c,status:'assessed',gaps:[],method:'fresh trace',evidence:['captured source']})),gaps:[]}));expect(command(['submit',original.runId,submission]).status).toBe(0);expect(command(['finish',original.runId]).status).toBe(0);const findingId=JSON.parse(fs.readFileSync(reportPath,'utf8')).findings[0].id,rechecked=command(['recheck',findingId,'--run',original.runId,'--repo',repo]);expect(rechecked.status).toBe(0);const child=JSON.parse(rechecked.stdout),childPath=path.join(state,'security','cso',original.repoId,child.runId,'report.json'),childReport=JSON.parse(fs.readFileSync(childPath,'utf8')),claim=path.join(root,'recheck-claim.json'),variant={...finding,title:'Moved cross-tenant user read',location:{...finding.location,symbol:'movedTenantQuery'}};fs.writeFileSync(claim,JSON.stringify({application,findings:[variant],coverage:childReport.coverage.filter((c:any)=>!['snapshot-inputs','history-inputs'].includes(c.domain)).map((c:any)=>({...c,status:'assessed',gaps:[],method:'fresh current-source trace',evidence:['new snapshot']})),gaps:[],recheck:{findingId,outcome:'resolved',evidence:[{kind:'caller',path:'src/users.ts',line:1,observation:'Fresh caller trace reaches the tenant predicate'},{kind:'security_boundary',path:'src/users.ts',line:1,observation:'Fresh boundary trace checks cross-tenant denial'}],rootCause}}));expect(command(['submit',child.runId,claim]).status).toBe(0);const finished=command(['finish',child.runId]);expect(finished.status).not.toBe(0);expect(finished.stderr).toContain('surviving root-cause');expect(JSON.parse(fs.readFileSync(childPath,'utf8')).status).toBe('running');});
|
||||
test('doctor performs no downloads and rejects a remote Docker endpoint',()=>{const r=command(['doctor','--repo',repo],{DOCKER_HOST:'tcp://127.0.0.1:2375'});expect(r.status).toBe(0);const value=JSON.parse(r.stdout);expect(value.downloads).toBe(false);expect(value.checks.find((x:any)=>x.capability==='local-docker-isolation')).toMatchObject({status:'missing'});expect(JSON.stringify(value)).toContain('Remote TCP');});
|
||||
test('doctor returns exact missing capabilities for an unavailable repository',()=>{const r=command(['doctor','--repo',path.join(root,'missing-repository')],{DOCKER_HOST:'tcp://127.0.0.1:2375'});expect(r.status).toBe(0);const value=JSON.parse(r.stdout);expect(value.elapsedMs).toBeLessThan(30_000);expect(value.checks.find((x:any)=>x.capability==='static-snapshot')).toMatchObject({status:'missing'});expect(value.checks.find((x:any)=>x.capability==='application-preparation')).toMatchObject({status:'missing'});expect(value.checks.find((x:any)=>x.capability==='qualified-runtimes')).toMatchObject({status:'missing'});});
|
||||
test('audits nonignored source in a newly initialized repository before its first commit',()=>{
|
||||
const unborn=path.join(root,'unborn-repo');fs.mkdirSync(unborn);const runGit=(...args:string[])=>{const result=spawnSync('/usr/bin/git',['-C',unborn,...args],{encoding:'utf8',env:{HOME:root,PATH:'/usr/bin:/bin'},timeout:30_000});if(result.status)throw new Error(result.stderr);};runGit('init','-q');fs.writeFileSync(path.join(unborn,'app.js'),'export const newProject = true\n');
|
||||
const diagnosed=command(['doctor','--repo',unborn],{DOCKER_HOST:'tcp://127.0.0.1:2375'});expect(diagnosed.status).toBe(0);expect(JSON.parse(diagnosed.stdout).checks.find((item:any)=>item.capability==='static-snapshot')).toMatchObject({status:'ready'});
|
||||
const started=command(['start','--repo',unborn,'--scope','auth','--offline']);expect(started.status).toBe(0);const run=JSON.parse(started.stdout),dir=path.join(state,'security','cso',run.repoId,run.runId),manifest=JSON.parse(fs.readFileSync(path.join(dir,'snapshot.json'),'utf8')),history=JSON.parse(fs.readFileSync(path.join(dir,'history-status.json'),'utf8'));
|
||||
expect(manifest).not.toHaveProperty('headCommit');expect(manifest.entries.find((item:any)=>item.path==='app.js')?.executionHash).toMatch(/^[a-f0-9]{64}$/);expect(history).toEqual({status:'captured',range:'unborn HEAD',commits:0,bytes:0});
|
||||
});
|
||||
test('state configured inside the audited repository is rejected before changing it',()=>{const before=git('status','--porcelain=v1','-z'),r=command(['start','--repo',repo],{GSTACK_HOME:path.join(repo,'.private-state')});expect(r.status).not.toBe(0);expect(r.stderr).toContain('UNSAFE_PATH');expect(fs.existsSync(path.join(repo,'.private-state'))).toBe(false);expect(git('status','--porcelain=v1','-z')).toBe(before);});
|
||||
});
|
||||
Reference in New Issue
Block a user