#!/usr/bin/env bun import * as fs from 'node:fs'; import * as os from 'node:os'; import { randomBytes } from 'node:crypto'; import { basename, dirname, isAbsolute, join, resolve } from 'node:path'; import { ABI, ApplicationModel, CoverageRecord, CsoError, FindingV3, PreparationProof, RunPolicy, RunReportV3, SnapshotEntry, SnapshotManifest, SubmissionV3, canonical, completeness, importLegacy, object, relativePath, renderReport, rootCauseIdentity, sha256, snapshotPathHandle, snapshotPathHandleId, snapshotPathId, snapshotReference, string, strings, validateCoverage, validateFinding, validateVerificationRequest, } from './contracts'; import { capture, containedFile, assertSnapshot } from './snapshot'; import { assertStateOutside, event, finalizeReplayTemporary, loadReport, newRun, privateRoot, publicReport, PUBLIC_SOURCE_ROOT, readJson, repoId, requireTime, retention, runDirectory, saveReport, secureDirectory, withLock, writeHelperJson, writeJson, writeJsonExclusive, } from './state'; import { dockerEndpoint, dockerProbe, ISOLATION_POLICY_HASH } from './docker'; import { executable, git, redact, sanitizeForJson, sanitizeHelperForJson } from './process'; import { inspectPreparation } from './preparation'; import { assertRuntimeCompatible, RUNTIME_CATALOG, selectRuntime, validateRuntimeCatalog, type RuntimeCatalog, } from './runtime-catalog'; import { PublicArchiveCache, publicArchiveCacheRoot } from './cache'; import { admitPreparationRuntime, admitPreparationSidecar, PreparationExecutor, type DependencyClosure, type RailsDatabaseSelection, } from './preparation-executor'; import { DockerPreparationSandboxRunner } from './preparation-docker'; import { importSarif, SCANNER_IDS, ScannerId } from './scanners'; import { SCANNER_CATALOG, selectScanner, validateScannerCatalog, type ScannerCatalog, } from './scanner-catalog'; import { executeScanner, scannerCoverage, validateScannerRequest } from './scanner-executor'; import { canonicalStartPlan, canonicalTestPlan, DockerVerificationExecutor, makeReviewArtifact, patchHash, validateRepairBundle, validateReviewArtifact, VerificationAttemptError, verificationHarnessHash, verifyRepair, type VerificationExecutor, } from './verification'; import { readBoundedStable } from './bounded-file'; import { assertionWitnessReplayHash, runAssertionWitnessChild } from './witness'; import { historyForPath } from './history'; import { catalogImageProvisioningPolicy, inspectCatalogImages, openLocalCatalogImageSession, provisionCatalogImages, qualifiedCatalogImages, type CatalogImageSessionFactory, } from './image-provisioning'; const VERSION = '3.0.0'; const RETENTION_MAINTENANCE_MS = 1_000, RETENTION_MAX_ENTRIES = 100_000, REPLAY_LOOKUP_MAX_ENTRIES = 10_000; const productionCatalogImageSession: CatalogImageSessionFactory = (deadline) => openLocalCatalogImageSession(process.env, deadline); /** Internal qualification seam. The public entrypoint below always supplies committed dependencies. */ export interface CsoCliDependencies { readonly runtimeCatalog: RuntimeCatalog; readonly scannerCatalog?: ScannerCatalog; readonly catalogImageSession?: CatalogImageSessionFactory; readonly watchdogPath: () => string; } const GENERATION_LOCK_FD = (() => { // Source-mode developer/test runs use Bun directly. For installed builds, // this catches accidental direct use of the internal payload. It is not an // authentication mechanism against the trusted same-user host: that user // can reproduce an inherited descriptor or environment value. The public // native launcher is the security boundary because it scrubs runtime and // loader variables before Bun starts. if (/^bun(?:\.exe)?$/i.test(basename(process.execPath))) return undefined; if (process.platform === 'win32') { if (process.env.GSTACK_CSO_GENERATION_GUARD !== 'inherited-windows-generation-handle-v3') throw new CsoError( 'ISOLATION_FAILED', 'Direct use of the internal CSO payload is unsupported; invoke gstack-cso-launcher', ); delete process.env.GSTACK_CSO_GENERATION_GUARD; return undefined; } const raw = process.env.GSTACK_CSO_GENERATION_LOCK_FD; if (raw === undefined || !/^(?:[3-9]|[1-9][0-9]+)$/.test(raw)) throw new CsoError( 'ISOLATION_FAILED', 'Direct use of the internal CSO payload is unsupported; invoke gstack-cso-launcher', ); const fd = Number(raw); let stat: fs.Stats; try { stat = fs.fstatSync(fd); } catch { throw new CsoError('ISOLATION_FAILED', 'The launcher publication lease was not preserved by the runtime'); } const install = fs.statSync(dirname(process.execPath)); if (!stat.isDirectory() || stat.dev !== install.dev || stat.ino !== install.ino) throw new CsoError( 'ISOLATION_FAILED', 'The launcher publication lease does not name the helper installation directory', ); delete process.env.GSTACK_CSO_GENERATION_LOCK_FD; return fd; })(); void GENERATION_LOCK_FD; const HELP = `gstack-cso ${VERSION} (helper ABI ${ABI}) Usage: gstack-cso start --repo PATH [--comprehensive] [--diff] [--base REF] [--budget SECONDS] [--offline] [--infra|--code|--skills|--supply-chain|--owasp|--scope DOMAIN] gstack-cso doctor --repo PATH gstack-cso provision-images [--setup-summary] [--per-image-seconds 5..300] gstack-cso resume RUN gstack-cso inspect RUN gstack-cso read RUN PATH_OR_HANDLE gstack-cso history RUN [PATH_OR_HANDLE] gstack-cso submit RUN SUBMISSION.json gstack-cso scan RUN gitleaks|osv|semgrep|zizmor|trivy|schemathesis [REQUEST.json] gstack-cso scanner-outcome RUN ARTIFACT_ID gstack-cso import-sarif RUN REPORT.sarif gstack-cso record-review RUN REQUEST.json --producer ID gstack-cso test-plan RUN node|bun|python|rails gstack-cso runtime-plan RUN node|bun|python|rails --port PORT gstack-cso verify RUN REQUEST.json gstack-cso patch-hash REQUEST.json gstack-cso finish RUN gstack-cso replay BUNDLE_ID [--source MATCHING_SOURCE] gstack-cso recheck FINDING --repo PATH [--run RUN] gstack-cso import-v2 REPORT.json gstack-cso inspect-v2 IMPORT_ID gstack-cso schema Static runs never execute application code. Target and scanner execution is Docker-only and requires a qualified immutable catalog.`; const SCHEMA = { version: 3, scanner: { profile: 'optional exact qualified scanner profile ID', api: { runtimeProfile: 'qualified app runtime ID; comprehensive mode only', port: '1024..65535', start: { executable: 'absolute in-container path', args: ['helper-derived literal argv with optional inspect handles'], }, control: { name: 'legitimate control', path: '/path', method: 'GET|POST|PUT|PATCH|DELETE', expected: { status: '100..599', includes: 'optional', excludes: 'optional' }, }, boundaryFiles: ['untransformed snapshot-relative path or inspect handle'], schema: 'reviewed OpenAPI 3.0/3.1 JSON; internal references; no server overrides, hooks, callbacks or external examples', operationIds: ['1..20 unique declared path operation IDs'], seed: 'optional 1..2147483647', maxExamples: 'optional 1..100', }, }, submission: { application: { actors: ['string'], assets: ['string'], entrypoints: ['string'], tenantBoundaries: ['string'], sensitiveOperations: ['string'], invariants: ['string'], }, findings: [ { title: 'string', rootCause: 'stable root cause', location: { path: 'exact path or opaque handle returned by inspect', line: 'positive integer', symbol: 'string', }, advisoryIds: ['normalized advisory identity or empty'], severity: 'critical|high|medium|low|informational', confidence: 'high|medium|low', confidenceRationale: 'why available evidence supports that confidence', evidence: 'supported|hypothesis', attackerControl: 'specific input/control', impact: 'specific consequence', scenario: 'concrete attacker scenario', trace: ['entrypoint', 'caller', 'sink'], references: ['supporting source/advisory reference'], recommendation: 'concrete root-cause repair', challenge: { reviewer: 'identity or exact sequential fallback label', independent: 'boolean', mode: 'independent_agent|sequential_fallback', callers: 'checked callers', controls: 'checked controls', counterevidence: 'checked counterevidence', conclusion: 'reasoned outcome', }, dependency: { affectedVersion: 'optional exact range/version', reachability: 'reachable|unreachable|unknown', exposure: 'production/build/development context', exploitation: 'published exploitation evidence or unknown', }, }, ], coverage: [ { domain: 'string', scope: 'string', status: 'assessed|partial|not_assessed|not_applicable', method: 'string', gaps: ['required for partial/not_assessed'], exclusions: ['string'], evidence: ['required for assessed/partial/not_applicable'], tool: { name: 'optional', version: 'exact', freshness: 'timestamp/status', outcome: 'string' }, }, ], gaps: ['string'], modelUsage: { source: 'host-reported source', tokens: 'nonnegative integer', cost: 'optional finite nonnegative number', }, recheck: { findingId: 'original stable ID', outcome: 'open|resolved|unknown', evidence: [ { kind: 'caller|security_boundary', path: 'fresh snapshot path or inspect handle', line: 'positive integer', observation: 'fresh source observation', }, ], rootCause: 'same root cause', }, }, verification: { findingId: 'stable ID', runtimeProfile: 'qualified runtime ID', port: '1024..65535', start: { executable: 'absolute in-container path', args: ['literal argv'] }, legitimate: [ { name: 'control name', path: '/numeric-loopback-relative path', method: 'GET|POST|PUT|PATCH|DELETE', headers: { 'optional-name': 'value' }, body: 'optional body', expected: { status: '100..599', includes: 'optional', excludes: 'optional' }, }, ], security: { name: 'security assertion', path: '/path', method: 'GET|POST|PUT|PATCH|DELETE', expected: { status: 'fixed status', includes: 'optional', excludes: 'optional' }, vulnerable: { status: 'provably mutually-exclusive vulnerable status', includes: 'optional', excludes: 'optional', }, }, existingTests: [ { executable: 'must exactly match the helper-derived canonical stack suite', args: ['helper-derived argv'], }, ], testFiles: ['exact immutable canonical path or inspect handle'], fixtures: { 'relative/path': 'content mounted read-only at /fixtures' }, boundaryFiles: ['snapshot path or inspect handle for the security boundary'], changes: [ { path: 'snapshot path or inspect handle', beforeSha256: 'hash or null', after: 'replacement or null', effect: 'source|configuration|dependency', }, ], review: { artifactId: 'helper-issued after record-review', reviewer: 'self-attested identity distinct from producer', independent: 'self-attested boolean', rootCauseRepaired: 'self-attested boolean', featurePreserved: 'self-attested boolean', boundaryMocks: 'self-attested boolean', rationale: 'specific review', reviewedPatchHash: 'canonical patch hash', }, }, helperOwned: [ 'run/report completeness', 'stable IDs', 'reproduction outcome', 'repair result and label', 'current-source closure', 'verification/bundle hashes', ], }; function emit(value: unknown): void { process.stdout.write( (typeof value === 'string' ? redact(value) : JSON.stringify(sanitizeHelperForJson(value), null, 2)) + '\n', ); } function persistableArtifact(value: T, label: string): T { const sanitized = sanitizeHelperForJson(value) as T; if (canonical(sanitized) !== canonical(value)) throw new CsoError( 'REDACTION_FAILED', `${label} contains material that cannot be persisted without changing its authenticated identity`, ); return sanitized; } function rejectUnexpected(value: Record, allowed: readonly string[], name: string): void { for (const key of Object.keys(value)) if (!allowed.includes(key)) throw new CsoError('INVALID_SCHEMA', `Unexpected ${name} field: ${key}`); } function need(args: string[], flag: string): string { const i = args.indexOf(flag); if (i < 0 || i === args.length - 1 || args[i + 1].startsWith('--')) throw new CsoError('INVALID_ARGUMENT', `${flag} requires a value`); const v = args[i + 1]; args.splice(i, 2); return v; } function take(args: string[], flag: string): boolean { const i = args.indexOf(flag); if (i < 0) return false; args.splice(i, 1); return true; } function callerPath(value: string): string { if (isAbsolute(value)) return resolve(value); const cwd = process.env.GSTACK_CSO_CALLER_CWD; if (!cwd || !isAbsolute(cwd)) throw new CsoError('INVALID_ARGUMENT', 'Relative paths require the trusted gstack-cso launcher'); return resolve(cwd, value); } function readInput(path: string, max = 1024 * 1024): unknown { let data: Buffer; try { data = readBoundedStable(callerPath(path), max, 'Input file'); } catch (error) { if (error instanceof CsoError) throw error; throw new CsoError('MISSING_INPUT', `Input file does not exist: ${path}`); } try { return JSON.parse(data.toString('utf8')); } catch { throw new CsoError('INVALID_SCHEMA', 'Input is not valid JSON'); } } function model(v: unknown): ApplicationModel { const x = object(v, 'application model'); rejectUnexpected( x, ['actors', 'assets', 'entrypoints', 'tenantBoundaries', 'sensitiveOperations', 'invariants'], 'application model', ); const out: ApplicationModel = { actors: strings(x.actors, 'actors'), assets: strings(x.assets, 'assets'), entrypoints: strings(x.entrypoints, 'entrypoints'), tenantBoundaries: strings(x.tenantBoundaries, 'tenantBoundaries'), sensitiveOperations: strings(x.sensitiveOperations, 'sensitiveOperations'), invariants: strings(x.invariants, 'invariants'), }; if (Object.values(out).some((a) => !a.length)) throw new CsoError( 'INVALID_SCHEMA', 'Every application-model dimension needs at least one evidence-backed entry', ); return out; } function planned(scope: string): CoverageRecord[] { const domains = scope === 'infra' ? ['secrets', 'dependencies', 'ci-cd', 'infrastructure', 'integrations'] : scope === 'code' ? ['llm-agentic-mcp', 'owasp-2025', 'stride', 'data-classification'] : scope === 'skills' ? ['skill-supply-chain'] : scope === 'supply-chain' ? ['dependencies'] : scope === 'owasp' ? ['owasp-2025'] : scope.startsWith('domain:') ? [scope.slice(7)] : [ 'secrets', 'dependencies', 'ci-cd', 'infrastructure', 'integrations', 'llm-agentic-mcp', 'skill-supply-chain', 'owasp-2025', 'stride', 'data-classification', ]; return ['application-model', 'attack-surface', ...domains].map((domain) => ({ domain, scope, status: 'not_assessed', method: 'pending investigation', gaps: ['Assessment has not been submitted'], exclusions: [], evidence: [], })); } function snapshotCoverage(manifest: Awaited>, scope: string): CoverageRecord { const omitted = manifest.entries.filter((entry) => !entry.executionHash), excluded = omitted.filter((entry) => entry.transformation?.startsWith('excluded:')); // Classify every unexplained omission as a material coverage gap. Coverage // must not depend on transformation prose retaining a particular prefix. const unread = omitted.filter((entry) => !excluded.includes(entry)); const deleted = manifest.deletedPaths ?? [], captured = manifest.entries.filter((entry) => entry.executionHash).length, missing = unread.length + deleted.length; return { domain: 'snapshot-inputs', scope, status: missing ? (captured ? 'partial' : 'not_assessed') : 'assessed', method: 'fail-closed captured source inventory', gaps: [ ...unread.map( (entry) => `${publicSnapshotPath(manifest, entry.path).path}: in-scope source payload was unread and withheld from static and runtime assessment`, ), ...deleted.map( (item) => `${publicSnapshotPath(manifest, item.path).path}: tracked source is deleted from the worktree; only retained history is available for assessment`, ), ], exclusions: excluded.map( (entry) => `${publicSnapshotPath(manifest, entry.path).path}: ${entry.transformation}`, ), evidence: [ `${captured} sanitized execution input${captured === 1 ? '' : 's'} captured; ${excluded.length} explicit non-executable exclusion${excluded.length === 1 ? '' : 's'}; ${unread.length} unread in-scope input${unread.length === 1 ? '' : 's'}; ${deleted.length} tracked deletion${deleted.length === 1 ? '' : 's'}`, ], }; } function historyCoverage(status: any, scope: string): CoverageRecord { return status?.status === 'captured' ? { domain: 'history-inputs', scope, status: 'assessed', method: 'bounded helper-retained Git history', gaps: [], exclusions: [], evidence: [ `Captured ${String(status.commits ?? 'bounded commits')} from ${String(status.range ?? 'the pinned source range')}`, ], } : { domain: 'history-inputs', scope, status: 'not_assessed', method: 'bounded helper-retained Git history', gaps: [ typeof status?.gap === 'string' && status.gap.trim() ? status.gap : 'Historical evidence was not safely retained', ], exclusions: [], evidence: [], }; } function helperOwnedCoverage(domain: string): boolean { return ( domain === 'snapshot-inputs' || domain === 'history-inputs' || domain === 'runtime-readiness' || domain.startsWith('scanner:') || domain.startsWith('preparation:') || domain.startsWith('execution:') ); } function parseStart(args: string[]): { repo: string; policy: RunPolicy; comparisonBase?: string } { const repo = callerPath(need(args, '--repo')), comprehensive = take(args, '--comprehensive'), diff = take(args, '--diff'), offline = take(args, '--offline'); const scopeFlags = ['--infra', '--code', '--skills', '--supply-chain', '--owasp'].filter((f) => args.includes(f), ); const named = args.includes('--scope') ? need(args, '--scope') : undefined; if (scopeFlags.length + (named ? 1 : 0) > 1) throw new CsoError('INVALID_ARGUMENT', 'Select only one scope'); for (const f of scopeFlags) take(args, f); const explicitBase = args.includes('--base'), base = explicitBase ? need(args, '--base') : 'origin/main'; const rawBudget = args.includes('--budget') ? need(args, '--budget') : String(comprehensive ? 1800 : 600), budgetSeconds = Number(rawBudget); if (!Number.isInteger(budgetSeconds) || budgetSeconds < 120 || budgetSeconds > (comprehensive ? 1800 : 600)) throw new CsoError( 'INVALID_ARGUMENT', `Budget must be an integer from 120 to ${comprehensive ? 1800 : 600} seconds`, ); if (args.length) throw new CsoError('INVALID_ARGUMENT', `Unknown argument: ${args[0]}`); if (!fs.existsSync(repo) || !fs.statSync(repo).isDirectory()) throw new CsoError('MISSING_INPUT', 'Repository directory does not exist'); const scope = named ? `domain:${string(named, 'scope', 100)}` : (scopeFlags[0]?.slice(2) ?? 'default'); return { repo, policy: { mode: comprehensive ? 'comprehensive' : 'daily', scope, diff, base, offline, budgetSeconds, maxWorkers: 3, maxRepairs: 3, }, ...(diff || explicitBase ? { comparisonBase: base } : {}), }; } async function start( args: string[], dependencies: CsoCliDependencies, parent?: RunReportV3['parent'], requiredAncestor?: string, startedAt = new Date(), ): Promise { const { repo, policy, comparisonBase } = parseStart(args), createdAt = startedAt; assertStateOutside(repo); if (!parent) retention(createdAt.getTime(), { deadlineMs: Math.min( createdAt.getTime() + RETENTION_MAINTENANCE_MS, createdAt.getTime() + policy.budgetSeconds * 1000 - 60_000, ), maxEntries: RETENTION_MAX_ENTRIES, }); const run = newRun(repo); let manifest: Awaited>; try { manifest = await capture(repo, run.dir, comparisonBase, requiredAncestor, { deadlineMs: createdAt.getTime() + policy.budgetSeconds * 1000 - 60_000, }); } catch (error) { fs.rmSync(run.dir, { recursive: true, force: true }); throw error; } const report: RunReportV3 = { schemaVersion: 3, runId: run.runId, repoId: run.repoId, createdAt: createdAt.toISOString(), deadline: new Date(createdAt.getTime() + policy.budgetSeconds * 1000).toISOString(), status: 'running', completeness: 'not assessed', policy, source: { root: repo, snapshotHash: manifest.executionHash, originalHash: manifest.originalHash, baseCommit: manifest.baseCommit, transformations: [ ...manifest.entries .filter((entry) => entry.transformation) .map((entry) => ({ path: publicSnapshotPath(manifest, entry.path).path, handling: entry.transformation!, })), ...(manifest.deletedPaths ?? []).map((item) => ({ path: publicSnapshotPath(manifest, item.path).path, handling: 'tracked source deleted; retained history only', })), ], }, application: { actors: [], assets: [], entrypoints: [], tenantBoundaries: [], sensitiveOperations: [], invariants: [], }, coverage: [ snapshotCoverage(manifest, policy.scope), historyCoverage(readJson(join(run.dir, 'history-status.json')), policy.scope), ...planned(policy.scope), ], findings: [], gaps: [], events: [], ...(parent ? { parent } : {}), }; event( report, 'snapshot', `Captured ${manifest.entries.length} source entries; ${manifest.entries.filter((e) => e.transformation).length + (manifest.deletedPaths?.length ?? 0)} transformations disclosed`, ); if (policy.mode === 'comprehensive') { const plan = inspectPreparation(join(run.dir, 'snapshot')); writeJson(join(run.dir, 'preparation.json'), plan); const c: CoverageRecord = { domain: 'runtime-readiness', scope: plan.stack, status: plan.status === 'ready' ? 'partial' : 'not_assessed', method: 'inert lockfile and runtime-catalog inspection', gaps: plan.prerequisites.map((p) => p.message), exclusions: [], evidence: [`Preparation metadata: ${plan.status}`], }; try { validateRuntimeCatalog(dependencies.runtimeCatalog); selectRuntime(plan.runtimeProfile, platform(), dependencies.runtimeCatalog); c.evidence.push(`Qualified runtime catalog: ${dependencies.runtimeCatalog.revision}`); } catch (error: any) { c.gaps.push( error?.message?.startsWith('MISSING_QUALIFIED_RUNTIME') ? error.message : 'Runtime catalog validation failed', ); } try { const runtimeHome = secureDirectory(join(run.dir, 'home')), endpoint = await dockerEndpoint(runtimeHome); const probe = await dockerProbe(endpoint, runtimeHome); c.evidence.push(`Local Docker ${probe.version} admitted at ${endpoint.uri}`); } catch (error: any) { c.gaps.push(error instanceof CsoError ? error.message : 'Local Docker isolation admission failed'); } if (plan.status === 'ready' && !c.gaps.length) c.status = 'assessed'; else if (c.evidence.length > 1) c.status = 'partial'; report.coverage.push(c); } saveReport(run.dir, report); return publicReport(report); } async function doctor(args: string[], dependencies: CsoCliDependencies) { const started = Date.now(), repo = callerPath(need(args, '--repo')); if (args.length) throw new CsoError('INVALID_ARGUMENT', `Unknown argument: ${args[0]}`); const staticCheck = (async () => { let home = ''; try { const stat = fs.statSync(repo); if (!stat.isDirectory()) throw new CsoError('MISSING_INPUT', 'Repository path is not a directory'); const g = executable('git'); home = secureDirectory(fs.mkdtempSync(join(fs.realpathSync(os.tmpdir()), 'gstack-cso-doctor-git-'))); if ((await git(repo, ['rev-parse', '--is-inside-work-tree'], home)).trim() !== 'true') throw new CsoError('MISSING_INPUT', 'Repository path is not a Git working tree'); return { capability: 'static-snapshot', status: 'ready', detail: g }; } catch (e: any) { return { capability: 'static-snapshot', status: 'missing', detail: e instanceof CsoError ? e.message : 'Repository path is missing or unreadable', }; } finally { if (home) fs.rmSync(home, { recursive: true, force: true }); } })(); let preparation: ReturnType | undefined; try { const stat = fs.statSync(repo); if (!stat.isDirectory()) throw new CsoError('MISSING_INPUT', 'Repository path is not a directory'); preparation = inspectPreparation(repo); } catch {} const scannerCatalog = dependencies.scannerCatalog ?? SCANNER_CATALOG, imageSession = dependencies.catalogImageSession ?? productionCatalogImageSession, deadline = started + 30_000; let targetPlatform: 'linux/amd64' | 'linux/arm64' | undefined, entries: ReturnType = []; try { targetPlatform = platform(); entries = qualifiedCatalogImages(dependencies.runtimeCatalog, scannerCatalog, targetPlatform); } catch {} const inspectedPromise = inspectCatalogImages(entries, imageSession, deadline); const checks: any[] = [await staticCheck]; checks.push( preparation ? { capability: 'application-preparation', status: preparation.status === 'ready' ? 'ready' : 'missing', detail: { stack: preparation.stack, prerequisites: preparation.prerequisites }, } : { capability: 'application-preparation', status: 'missing', detail: 'Repository source is unavailable for inert preparation inspection', }, ); const inspected = await inspectedPromise; checks.push({ capability: 'local-docker-isolation', status: inspected.docker.status, detail: inspected.docker.detail, }); try { if (!preparation || preparation.status !== 'ready') throw new CsoError('PREREQUISITE', 'Resolve the application-preparation prerequisites first'); if (!targetPlatform) throw new CsoError('PREREQUISITE', 'Qualified runtimes require an amd64/arm64 Linux Docker platform'); validateRuntimeCatalog(dependencies.runtimeCatalog); const runtime = selectRuntime(preparation.runtimeProfile, targetPlatform, dependencies.runtimeCatalog), availability = inspected.images.find((item) => item.kind === 'runtime' && item.id === runtime.id), requiredSidecars: Array> = [], prerequisites: string[] = []; if (!availability || availability.status !== 'available') prerequisites.push( availability?.reason ?? 'Exact qualified runtime image is not present in the local Docker daemon; rerun setup with Docker and public registry access', ); if (preparation.stack === 'rails' && preparation.database?.selected === 'postgresql') { const sidecar = selectRuntime('postgresql', targetPlatform, dependencies.runtimeCatalog), sidecarAvailability = inspected.images.find( (item) => item.kind === 'runtime' && item.id === sidecar.id, ), sidecarReady = sidecarAvailability?.status === 'available', prerequisite = sidecarReady ? undefined : (sidecarAvailability?.reason ?? 'Exact qualified PostgreSQL sidecar image is not present in the local Docker daemon; rerun setup with Docker and public registry access'); if (prerequisite) prerequisites.push(prerequisite); requiredSidecars.push({ kind: 'postgresql', profile: sidecar.id, image: sidecar.image, platform: targetPlatform, availability: sidecarReady ? 'available' : 'unavailable', ...(prerequisite ? { prerequisite } : {}), }); } const ready = !prerequisites.length; checks.push({ capability: 'qualified-runtimes', status: ready ? 'ready' : 'missing', detail: { catalog: dependencies.runtimeCatalog.revision, profile: runtime.id, image: runtime.image, platform: targetPlatform, availability: ready ? 'available' : 'unavailable', ...(requiredSidecars.length ? { requiredSidecars } : {}), ...(prerequisites.length ? { prerequisite: prerequisites[0], prerequisites } : {}), }, }); } catch (error: any) { checks.push({ capability: 'qualified-runtimes', status: 'missing', detail: error instanceof CsoError ? error.message : (error?.message ?? 'Qualified runtime catalog is invalid'), }); } for (const id of SCANNER_IDS) { try { if (!targetPlatform) throw new CsoError('PREREQUISITE', 'Scanner containers require an amd64/arm64 Linux Docker platform'); validateScannerCatalog(scannerCatalog); const profile = selectScanner(id, targetPlatform, undefined, scannerCatalog), availability = inspected.images.find((item) => item.kind === 'scanner' && item.id === profile.id); if (!availability || availability.status !== 'available') checks.push({ capability: `scanner:${id}`, status: 'missing', detail: { catalog: scannerCatalog.revision, profile: profile.id, image: profile.image, version: profile.version, qualifiedAt: profile.qualifiedAt, availability: 'unavailable', prerequisite: availability?.reason ?? 'Exact qualified scanner image is not present in the local Docker daemon; rerun setup with Docker and public registry access', }, }); else checks.push({ capability: `scanner:${id}`, status: 'ready', detail: { catalog: scannerCatalog.revision, profile: profile.id, image: profile.image, version: profile.version, qualifiedAt: profile.qualifiedAt, availability: 'available', }, }); } catch (error: any) { checks.push({ capability: `scanner:${id}`, status: 'missing', detail: error instanceof CsoError ? error.message : (error?.message ?? 'Qualified scanner catalog is invalid'), }); } } return { schemaVersion: 3, downloads: false, elapsedMs: Date.now() - started, checks }; } async function provisionImages(args: string[], dependencies: CsoCliDependencies): Promise { const setupSummary = take(args, '--setup-summary'), requestedSeconds = args.includes('--per-image-seconds') ? need(args, '--per-image-seconds') : undefined; if (args.length) throw new CsoError('INVALID_ARGUMENT', `Unknown argument: ${args[0]}`); if (requestedSeconds !== undefined) catalogImageProvisioningPolicy(0, requestedSeconds); let targetPlatform: 'linux/amd64' | 'linux/arm64'; try { targetPlatform = platform(); } catch (error) { const reason = error instanceof CsoError ? error.message : 'Qualified image provisioning requires an amd64/arm64 Linux Docker platform', result = { schemaVersion: 1, status: 'not_available', downloads: true, platform: 'unsupported', requested: 0, inspected: 0, alreadyPresent: 0, downloaded: 0, deadlineReached: false, unavailable: [], summary: `Qualified CSO images were not preloaded: ${reason}. Static audits remain available.`, }; return setupSummary ? result.summary : result; } const scannerCatalog = dependencies.scannerCatalog ?? SCANNER_CATALOG, entries = qualifiedCatalogImages(dependencies.runtimeCatalog, scannerCatalog, targetPlatform), policy = catalogImageProvisioningPolicy(entries.length, requestedSeconds), deadline = Date.now() + policy.aggregateMs, result = await provisionCatalogImages( entries, targetPlatform, dependencies.catalogImageSession ?? productionCatalogImageSession, deadline, policy.perImageMs, ); return setupSummary ? result.summary : result; } function run(args: string[]) { if (!args.length) throw new CsoError('INVALID_ARGUMENT', 'Run ID is required'); return { dir: runDirectory(args.shift()!), report: null as any }; } function recoveryEvents(dir: string): string[] { const out: string[] = []; let visited = 0; const walk = (at: string, depth: number) => { if (depth > 6 || visited++ > 4000) return; let entries: fs.Dirent[]; try { entries = fs.readdirSync(at, { withFileTypes: true }); } catch { return; } for (const entry of entries) { if (!/^[A-Za-z0-9._-]{1,120}$/.test(entry.name)) continue; const path = join(at, entry.name); let stat: fs.Stats; try { stat = fs.lstatSync(path); } catch { continue; } if (stat.isSymbolicLink()) continue; if (stat.isDirectory()) { walk(path, depth + 1); continue; } if (!['attempt.event', 'watchdog.event'].includes(entry.name) || !stat.isFile() || stat.size > 8192) continue; try { const message = redact(fs.readFileSync(path, 'utf8').trim()); if (message && !out.includes(message)) out.push(message); } catch {} } }; for (const name of ['supervision', 'preparation-execution']) { const root = join(dir, name); if (!fs.existsSync(root)) continue; const stat = fs.lstatSync(root); if (stat.isSymbolicLink() || !stat.isDirectory()) throw new CsoError('UNSAFE_PATH', 'Watchdog recovery state is not a private directory'); walk(root, 0); } return out; } function publicSnapshotPath( manifest: SnapshotManifest, path: string, ): { path: string; displayPath?: string } { const entry = manifest.entries.find((item) => item.path === path), handle = snapshotPathHandle(entry?.pathId ?? snapshotPathId(manifest.root, path)); let displayPath: string; try { displayPath = redact(path); } catch { displayPath = '[sensitive path withheld]'; } return displayPath === path ? { path } : { path: handle, displayPath }; } function publicSnapshotManifest(manifest: SnapshotManifest): Record { return { ...manifest, root: PUBLIC_SOURCE_ROOT, entries: manifest.entries.map((entry) => { const { path, pathId: _, ...rest } = entry; return { ...rest, ...publicSnapshotPath(manifest, path) }; }), ...(manifest.deletedPaths?.length ? { deletedPaths: manifest.deletedPaths.map((item) => publicSnapshotPath(manifest, item.path)) } : {}), ...(manifest.changedPaths ? { changedPaths: manifest.changedPaths.map((path) => publicSnapshotPath(manifest, path).path) } : {}), }; } function resolveSnapshotPath( manifest: SnapshotManifest, value: unknown, requireEntry: boolean, label = 'Snapshot path', allowDeleted = false, ): { path: string; entry?: SnapshotEntry } { const reference = snapshotReference(value), handleId = snapshotPathHandleId(reference); if (handleId) { const entry = manifest.entries.find((item) => item.pathId === handleId); if (entry) return { path: entry.path, entry }; const deleted = manifest.deletedPaths?.find((item) => item.pathId === handleId), changed = manifest.changedPaths?.find((path) => snapshotPathId(manifest.root, path) === handleId); if (allowDeleted && deleted) return { path: deleted.path }; if (!requireEntry && changed) return { path: changed }; throw new CsoError('INVALID_SCHEMA', `${label} handle is outside the retained inventory: ${reference}`); } const path = relativePath(reference), entry = manifest.entries.find((item) => item.path === path), deleted = manifest.deletedPaths?.find((item) => item.path === path), changed = manifest.changedPaths?.includes(path); if (entry) return { path, entry }; if (allowDeleted && deleted) return { path }; if (!requireEntry && changed) return { path }; throw new CsoError('INVALID_SCHEMA', `${label} is outside the retained inventory: ${reference}`); } type BoundRecheckEvidence = { kind: 'caller' | 'security_boundary'; path: string; line: number; observation: string; sourceState: 'present' | 'absent'; snapshotHash: string; sourceHash?: string; executionHash?: string; }; type BoundRecheckClaim = { findingId: string; outcome: 'open' | 'resolved' | 'unknown'; evidence: BoundRecheckEvidence[]; rootCause: string; }; function assertRecheckLine( runDir: string, path: string, entry: SnapshotEntry, line: number, label: string, ): void { if (!entry.executionHash) throw new CsoError( 'INVALID_SCHEMA', `${label} must reference source available in the fresh execution snapshot`, ); const body = readBoundedStable( containedFile(join(runDir, 'snapshot'), path), 64 * 1024 * 1024, label, ).toString('utf8'), lines = body.length ? (body.endsWith('\n') ? body.slice(0, -1) : body).split('\n').length : 0; if (line > lines) throw new CsoError('INVALID_SCHEMA', `${label} line is outside the fresh source file`); } function originalBoundary(report: RunReportV3): { dir: string; report: RunReportV3; manifest: SnapshotManifest; finding: FindingV3; path: string; } { if (!report.parent) throw new CsoError('INVALID_SCHEMA', 'Recheck evidence requires a linked original finding'); const dir = runDirectory(report.parent.runId), original = loadReport(dir), manifest = readJson(join(dir, 'snapshot.json')) as SnapshotManifest, finding = original.findings.find((item) => item.id === report.parent!.findingId); if (report.repoId !== original.repoId) throw new CsoError('INCOMPATIBLE_INPUT', 'Recheck repository identity differs from the original audit'); if (!finding) throw new CsoError('MISSING_INPUT', 'Original recheck finding no longer exists'); const path = resolveSnapshotPath( manifest, finding.location.path, false, 'Original finding boundary', true, ).path; return { dir, report: original, manifest, finding, path }; } function bindRecheckEvidence( value: unknown, runDir: string, manifest: SnapshotManifest, boundary: ReturnType, outcome: BoundRecheckClaim['outcome'], ): BoundRecheckEvidence[] { if (!Array.isArray(value) || value.length < 1 || value.length > 20) throw new CsoError('INVALID_SCHEMA', 'Recheck evidence must contain 1 to 20 fresh source observations'); const evidence = value.map((raw, index) => { const item = object(raw, `recheck evidence[${index}]`); rejectUnexpected(item, ['kind', 'path', 'line', 'observation'], `recheck evidence[${index}]`); const kind = string(item.kind, `recheck evidence[${index}].kind`, 32); if (!['caller', 'security_boundary'].includes(kind)) throw new CsoError('INVALID_SCHEMA', 'Recheck evidence kind must be caller or security_boundary'); if (!Number.isSafeInteger(item.line) || item.line < 1) throw new CsoError('INVALID_SCHEMA', `recheck evidence[${index}].line must be a positive integer`); const observation = redact(string(item.observation, `recheck evidence[${index}].observation`, 2048)), reference = snapshotReference(item.path); let selected: { path: string; entry?: SnapshotEntry } | undefined; try { selected = resolveSnapshotPath(manifest, reference, true, `recheck evidence[${index}].path`); } catch (error) { if (kind !== 'security_boundary') throw error; let old: { path: string }; try { old = resolveSnapshotPath( boundary.manifest, reference, false, `recheck evidence[${index}].path`, true, ); } catch { throw error; } if (old.path !== boundary.path || manifest.entries.some((entry) => entry.path === boundary.path)) throw error; if (item.line !== boundary.finding.location.line) throw new CsoError( 'INVALID_SCHEMA', 'Absent security-boundary evidence must cite the original finding line', ); return { kind: 'security_boundary' as const, path: snapshotPathHandle(snapshotPathId(manifest.root, boundary.path)), line: item.line as number, observation, sourceState: 'absent' as const, snapshotHash: manifest.originalHash, }; } if (!selected.entry || selected.entry.originalHash === 'not-read') throw new CsoError( 'INVALID_SCHEMA', 'Recheck evidence must reference freshly captured readable source', ); assertRecheckLine( runDir, selected.path, selected.entry, item.line as number, `recheck evidence[${index}]`, ); if (kind === 'security_boundary' && selected.path !== boundary.path) throw new CsoError( 'INVALID_SCHEMA', 'Security-boundary evidence must reference the original finding location', ); return { kind: kind as BoundRecheckEvidence['kind'], path: snapshotPathHandle(selected.entry.pathId), line: item.line as number, observation, sourceState: 'present' as const, snapshotHash: manifest.originalHash, sourceHash: selected.entry.originalHash, executionHash: selected.entry.executionHash, }; }); const identities = new Set(evidence.map((item) => canonical(item))); if (identities.size !== evidence.length) throw new CsoError('INVALID_SCHEMA', 'Recheck evidence contains duplicate observations'); if ( outcome === 'resolved' && (!evidence.some((item) => item.kind === 'caller' && item.sourceState === 'present') || !evidence.some((item) => item.kind === 'security_boundary')) ) throw new CsoError( 'INVALID_SCHEMA', 'Resolved closure requires fresh caller evidence and evidence for the original security boundary', ); return evidence; } function validateBoundRecheckClaim( value: unknown, runDir: string, manifest: SnapshotManifest, boundary: ReturnType, ): BoundRecheckClaim { const raw = object(value, 'retained recheck claim'); rejectUnexpected(raw, ['findingId', 'outcome', 'evidence', 'rootCause'], 'retained recheck claim'); const findingId = string(raw.findingId, 'retained recheck findingId'), rootCause = string(raw.rootCause, 'retained recheck rootCause'), outcome = raw.outcome; if (!['open', 'resolved', 'unknown'].includes(outcome as string)) throw new CsoError('INVALID_SCHEMA', 'Retained recheck outcome is invalid'); if (!Array.isArray(raw.evidence) || raw.evidence.length < 1 || raw.evidence.length > 20) throw new CsoError('INVALID_SCHEMA', 'Retained recheck evidence is invalid'); const evidence = raw.evidence.map((itemRaw, index) => { const item = object(itemRaw, `retained recheck evidence[${index}]`); rejectUnexpected( item, ['kind', 'path', 'line', 'observation', 'sourceState', 'snapshotHash', 'sourceHash', 'executionHash'], `retained recheck evidence[${index}]`, ); const kind = string(item.kind, `retained recheck evidence[${index}].kind`, 32), sourceState = string(item.sourceState, `retained recheck evidence[${index}].sourceState`, 16); if (!['caller', 'security_boundary'].includes(kind) || !['present', 'absent'].includes(sourceState)) throw new CsoError('INVALID_SCHEMA', 'Retained recheck evidence type is invalid'); if (!Number.isSafeInteger(item.line) || item.line < 1) throw new CsoError('INVALID_SCHEMA', 'Retained recheck evidence line is invalid'); const observation = string(item.observation, `retained recheck evidence[${index}].observation`, 2048), reference = snapshotReference(item.path); if (item.snapshotHash !== manifest.originalHash) throw new CsoError( 'INCOMPATIBLE_INPUT', 'Retained recheck evidence is not bound to the complete fresh snapshot inventory', ); if (sourceState === 'present') { const selected = resolveSnapshotPath(manifest, reference, true, 'Retained recheck evidence path'); if ( !selected.entry || selected.entry.originalHash === 'not-read' || typeof item.sourceHash !== 'string' || item.sourceHash !== selected.entry.originalHash || typeof item.executionHash !== 'string' || item.executionHash !== selected.entry.executionHash ) throw new CsoError( 'INCOMPATIBLE_INPUT', 'Retained recheck evidence is not bound to the fresh snapshot', ); assertRecheckLine( runDir, selected.path, selected.entry, item.line as number, `retained recheck evidence[${index}]`, ); if (kind === 'security_boundary' && selected.path !== boundary.path) throw new CsoError('INCOMPATIBLE_INPUT', 'Retained security-boundary evidence changed location'); return { kind: kind as BoundRecheckEvidence['kind'], path: snapshotPathHandle(selected.entry.pathId), line: item.line as number, observation, sourceState: 'present' as const, snapshotHash: item.snapshotHash as string, sourceHash: item.sourceHash, executionHash: item.executionHash, }; } if (kind !== 'security_boundary' || item.sourceHash !== undefined || item.executionHash !== undefined) throw new CsoError( 'INVALID_SCHEMA', 'Only an absent original security boundary can use absent evidence', ); const old = resolveSnapshotPath( boundary.manifest, reference, false, 'Retained absent security boundary', true, ); if ( old.path !== boundary.path || manifest.entries.some((entry) => entry.path === boundary.path) || item.line !== boundary.finding.location.line ) throw new CsoError( 'INCOMPATIBLE_INPUT', 'Retained absent-boundary evidence does not match the fresh snapshot', ); return { kind: 'security_boundary' as const, path: snapshotPathHandle(snapshotPathId(manifest.root, boundary.path)), line: item.line as number, observation, sourceState: 'absent' as const, snapshotHash: item.snapshotHash as string, }; }); if ( outcome === 'resolved' && (!evidence.some((item) => item.kind === 'caller' && item.sourceState === 'present') || !evidence.some((item) => item.kind === 'security_boundary')) ) throw new CsoError( 'INVALID_SCHEMA', 'Resolved closure lacks caller or original security-boundary evidence', ); if (new Set(evidence.map((item) => canonical(item))).size !== evidence.length) throw new CsoError('INVALID_SCHEMA', 'Retained recheck evidence contains duplicates'); return { findingId, outcome: outcome as BoundRecheckClaim['outcome'], evidence, rootCause }; } function requireReportingTime(report: RunReportV3): void { if (Date.now() >= Date.parse(report.deadline)) throw new CsoError('DEADLINE', 'Audit deadline reached; no further evidence can be accepted'); } function submit(args: string[]) { const { dir } = run(args); if (args.length !== 1) throw new CsoError('INVALID_ARGUMENT', 'submit requires one JSON file'); const rawInput = object(readInput(args[0]), 'submission'); rejectUnexpected( rawInput, ['application', 'findings', 'coverage', 'gaps', 'modelUsage', 'recheck'], 'submission', ); const input = rawInput as SubmissionV3; return withLock(dir, () => { const report = loadReport(dir), manifest = readJson(join(dir, 'snapshot.json')); assertSnapshot(dir, manifest); requireReportingTime(report); if (report.status !== 'running') throw new CsoError('INVALID_SCHEMA', 'Only a running audit accepts evidence'); if (input.findings !== undefined && !Array.isArray(input.findings)) throw new CsoError('INVALID_SCHEMA', 'submission.findings must be an array'); if (input.coverage !== undefined && !Array.isArray(input.coverage)) throw new CsoError('INVALID_SCHEMA', 'submission.coverage must be an array'); if (input.application) report.application = model(input.application); for (const raw of input.findings ?? []) { const sourceFinding = validateFinding(raw), sourceLocation = resolveSnapshotPath( manifest, sourceFinding.location.path, false, 'Finding path', true, ); if ( report.policy.diff && (!Array.isArray(manifest.changedPaths) || !manifest.changedPaths.includes(sourceLocation.path)) ) throw new CsoError( 'INVALID_SCHEMA', `Diff-scope finding root cause is outside the captured changed paths: ${sourceFinding.location.path}`, ); const safeRaw = object(sanitizeForJson(raw), 'finding'), safeLocation = object(safeRaw.location, 'location'); safeLocation.path = publicSnapshotPath(manifest, sourceLocation.path).path; const f = validateFinding(safeRaw), normalizedLocation = resolveSnapshotPath(manifest, f.location.path, false, 'Finding path', true); if (normalizedLocation.path !== sourceLocation.path) throw new CsoError('INVALID_SCHEMA', 'Finding path identity changed during redaction'); if (report.policy.mode === 'daily' && f.evidence === 'hypothesis') throw new CsoError('INVALID_SCHEMA', 'Daily reports contain supported findings only'); const old = report.findings.findIndex((x) => x.fingerprint === f.fingerprint); if (old < 0) { report.findings.push(f); event(report, 'early-finding', `${f.severity} ${f.evidence} finding ${f.id}`); } else report.findings[old] = { ...f, reproduction: report.findings[old].reproduction, repair: report.findings[old].repair, closure: report.findings[old].closure, verificationId: report.findings[old].verificationId, reproductionAttemptId: report.findings[old].reproductionAttemptId, verificationAssurance: report.findings[old].verificationAssurance, }; } for (const raw of input.coverage ?? []) { const c = validateCoverage(raw); if (helperOwnedCoverage(c.domain)) throw new CsoError('INVALID_SCHEMA', `Coverage domain is helper-owned: ${c.domain}`); const i = report.coverage.findIndex((x) => x.domain === c.domain && x.scope === c.scope); if (i < 0) report.coverage.push(c); else report.coverage[i] = c; } if (input.gaps) report.gaps = strings(input.gaps, 'gaps'); if (input.modelUsage) { const u = object(input.modelUsage, 'model usage'); rejectUnexpected(u, ['source', 'tokens', 'cost'], 'model usage'); if ( !Number.isInteger(u.tokens) || u.tokens < 0 || ('cost' in u && (typeof u.cost !== 'number' || !Number.isFinite(u.cost) || u.cost < 0)) ) throw new CsoError('INVALID_SCHEMA', 'Model usage must be host-reported finite nonnegative numbers'); report.modelUsage = { source: string(u.source, 'usage source'), tokens: u.tokens, ...(typeof u.cost === 'number' ? { cost: u.cost } : {}), }; } let recheckClaim: BoundRecheckClaim | undefined; if (input.recheck) { const rawClaim = object(input.recheck, 'recheck claim'); rejectUnexpected(rawClaim, ['findingId', 'outcome', 'evidence', 'rootCause'], 'recheck claim'); if (!report.parent || input.recheck.findingId !== report.parent.findingId) throw new CsoError('INVALID_SCHEMA', 'Recheck claim must target the linked original finding'); const outcome = input.recheck.outcome; if (!['open', 'resolved', 'unknown'].includes(outcome)) throw new CsoError('INVALID_SCHEMA', 'Recheck needs an open, resolved, or unknown outcome'); const boundary = originalBoundary(report), claim = { findingId: string(input.recheck.findingId, 'findingId'), outcome, evidence: bindRecheckEvidence(input.recheck.evidence, dir, manifest, boundary, outcome), rootCause: string(input.recheck.rootCause, 'rootCause'), }; recheckClaim = claim; } // A claim can close a prior finding. Publish it only after every report // mutation it relies on is durably accepted, so a failed submission never // leaves closure evidence behind. saveReport(dir, report); if (recheckClaim) writeHelperJson(join(dir, 'recheck-claim.json'), recheckClaim); return { runId: report.runId, findings: report.findings.length, completeness: report.completeness }; }); } function finish(args: string[]) { const { dir } = run(args); if (args.length) throw new CsoError('INVALID_ARGUMENT', 'finish takes only a run ID'); return withLock(dir, () => { const report = loadReport(dir), manifest = readJson(join(dir, 'snapshot.json')); assertSnapshot(dir, manifest); for (const c of report.coverage) if ( c.status === 'not_assessed' && !c.domain.startsWith('scanner:') && !report.gaps.includes(`${c.domain}: not assessed`) ) report.gaps.push(`${c.domain}: not assessed`); if (!report.application.actors.length && !report.gaps.includes('Application model was not completed')) report.gaps.push('Application model was not completed'); report.completeness = completeness(report); const persistTerminal = () => { report.status = 'finished'; if (!report.events.some((e) => e.kind === 'terminal')) event(report, 'terminal', 'Audit finished and retained according to the private-state policy'); saveReport(dir, report); return { runId: report.runId, status: report.status, completeness: report.completeness, report: 'report.md', }; }; if (report.parent && fs.existsSync(join(dir, 'recheck-claim.json'))) { const boundary = originalBoundary(report), claim = validateBoundRecheckClaim(readJson(join(dir, 'recheck-claim.json')), dir, manifest, boundary); if (claim.outcome === 'resolved') { if (report.completeness !== 'complete') throw new CsoError('INVALID_SCHEMA', 'Partial or incompatible rechecks cannot establish closure'); const originalDir = boundary.dir; return withLock(originalDir, () => { const original = loadReport(originalDir), finding = original.findings.find((f) => f.id === claim.findingId); if (report.repoId !== original.repoId) throw new CsoError( 'INCOMPATIBLE_INPUT', 'Recheck repository identity differs from the original audit', ); const survivingVariant = !!finding && report.findings.some( (candidate) => candidate.fingerprint === finding.fingerprint || rootCauseIdentity(candidate.rootCause) === rootCauseIdentity(finding.rootCause) || (candidate.advisoryIds.length > 0 && candidate.advisoryIds.some((id) => finding.advisoryIds.includes(id))), ); if ( !finding || finding.id !== boundary.finding.id || rootCauseIdentity(finding.rootCause) !== rootCauseIdentity(claim.rootCause) || survivingVariant ) throw new CsoError( 'INVALID_SCHEMA', 'Closure needs matching root cause, fresh caller and original-boundary evidence, and no surviving root-cause or advisory variant', ); const result = persistTerminal(); if (finding.closure !== 'resolved') { finding.closure = 'resolved'; event(original, 'closure', `Fresh recheck ${report.runId} resolved ${finding.id}`); saveReport(originalDir, original); } return result; }); } } return persistTerminal(); }); } async function inspect(args: string[]) { const { dir } = run(args); if (args.length) throw new CsoError('INVALID_ARGUMENT', 'inspect takes one run ID'); const report = loadReport(dir), manifest = readJson(join(dir, 'snapshot.json')) as SnapshotManifest; assertSnapshot(dir, manifest); const rawSensitive = readJson(join(dir, 'sensitive-evidence.json')), sensitiveEvidence = Array.isArray(rawSensitive) ? rawSensitive.map((item) => { if (!item || typeof item !== 'object' || typeof item.path !== 'string') return item; const id = snapshotPathHandleId(item.path), exact = id ? manifest.entries.find((entry) => entry.pathId === id)?.path : item.path; if (!exact) throw new CsoError( 'INCOMPATIBLE_INPUT', 'Sensitive-evidence path handle is outside the snapshot', ); return { ...item, ...publicSnapshotPath(manifest, exact) }; }) : rawSensitive; emit({ report, manifest: publicSnapshotManifest(manifest), history: readJson(join(dir, 'history-status.json')), sensitiveEvidence, preparation: fs.existsSync(join(dir, 'preparation.json')) ? readJson(join(dir, 'preparation.json')) : undefined, recovery: recoveryEvents(dir), }); } async function read(args: string[]) { const { dir } = run(args); if (args.length !== 1) throw new CsoError('INVALID_ARGUMENT', 'read requires one path or opaque handle'); const manifest = readJson(join(dir, 'snapshot.json')) as SnapshotManifest; assertSnapshot(dir, manifest); const selected = resolveSnapshotPath(manifest, args[0], true), full = containedFile(join(dir, 'readable'), selected.path), data = readBoundedStable(full, 1024 * 1024, 'Snapshot path'); emit(data.toString('utf8')); } async function history(args: string[]) { const { dir } = run(args), manifest = readJson(join(dir, 'snapshot.json')) as SnapshotManifest; assertSnapshot(dir, manifest); let selected: string | undefined; if (args.length) selected = resolveSnapshotPath(manifest, args.shift(), false, 'History path', true).path; if (args.length) throw new CsoError('INVALID_ARGUMENT', 'history accepts at most one path or opaque handle'); const status = readJson(join(dir, 'history-status.json')); if (status.status !== 'captured' || !fs.existsSync(join(dir, 'history.txt'))) throw new CsoError('MISSING_INPUT', status.gap || 'Historical evidence was not retained'); const raw = fs.readFileSync(join(dir, 'history.txt'), 'utf8'); if (!selected) { emit(raw); return; } const displayPath = publicSnapshotPath(manifest, selected).displayPath ?? selected, retained = historyForPath(raw, displayPath); emit(retained ?? `No retained patch hunks for ${displayPath}`); } function resume(args: string[]) { const { dir } = run(args); if (args.length) throw new CsoError('INVALID_ARGUMENT', 'resume takes one run ID'); return withLock(dir, () => { const report = loadReport(dir), manifest = readJson(join(dir, 'snapshot.json')); if (report.status === 'finished') throw new CsoError('INVALID_SCHEMA', 'A finished audit cannot be resumed'); assertSnapshot(dir, manifest); for (const message of recoveryEvents(dir)) if (!report.events.some((e) => e.kind === 'watchdog-recovery' && e.message === message)) event(report, 'watchdog-recovery', message); if (Date.now() >= Date.parse(report.deadline)) { report.status = 'interrupted'; event(report, 'deadline', 'Original budget is exhausted; resume did not replenish it'); saveReport(dir, report); throw new CsoError('DEADLINE', 'Original run budget is exhausted'); } report.status = 'running'; event(report, 'resume', 'Continued retained snapshot under original policy'); saveReport(dir, report); return { runId: report.runId, deadline: report.deadline, policy: report.policy, recovery: recoveryEvents(dir), }; }); } function importV2(args: string[]) { if (args.length !== 1) throw new CsoError('INVALID_ARGUMENT', 'import-v2 requires one report file'); const legacy = sanitizeForJson(importLegacy(readInput(args[0]))) as ReturnType, id = sha256(JSON.stringify(legacy)), dir = secureDirectory(join(privateRoot(), 'legacy-imports')); writeJson(join(dir, `${id}.json`), legacy); return { id, path: `legacy-imports/${id}.json`, warning: legacy.warning, report: legacy }; } function inspectV2(args: string[]) { if (args.length !== 1 || !/^[a-f0-9]{64}$/.test(args[0] ?? '')) throw new CsoError('INVALID_ARGUMENT', 'inspect-v2 requires the 64-character import ID'); const id = args[0], file = join(secureDirectory(join(privateRoot(), 'legacy-imports')), `${id}.json`); if (!fs.existsSync(file)) throw new CsoError('MISSING_INPUT', 'Legacy report import was not found or expired'); const report = readJson(file); if (report?.schemaVersion !== 2 || report?.readOnly !== true || !Array.isArray(report?.findings)) throw new CsoError('INCOMPATIBLE_INPUT', 'Stored legacy report is incompatible'); if (sha256(JSON.stringify(report)) !== id) throw new CsoError('INCOMPATIBLE_INPUT', 'Stored legacy report identity is inconsistent'); return { id, report }; } async function scanner(args: string[], sarif = false) { const { dir } = run(args); if ( sarif ? args.length !== 1 : args.length < 1 || args.length > 2 || !SCANNER_IDS.includes(args[0] as ScannerId) ) throw new CsoError( 'INVALID_ARGUMENT', sarif ? 'import-sarif needs one file' : 'scan requires a supported scanner ID and optional request JSON', ); const id = args[0] as ScannerId, request = !sarif ? validateScannerRequest(args[1] ? readInput(args[1]) : {}, id) : undefined; // A live writer owns the lock throughout the bounded scan. Finish, submit and // concurrent imports cannot replace coverage or retire the run underneath it. return await withLock(dir, async () => { const report = loadReport(dir); requireTime(report); if (report.status !== 'running') throw new CsoError('INVALID_SCHEMA', 'Scanner evidence can only enter a running audit'); let record: any; if (sarif) { const file = callerPath(args[0]); try { const data = readBoundedStable(file, 1024 * 1024, 'SARIF file'), out = importSarif(data.toString('utf8'), { sourceRoot: '/source' }); record = { outcome: out, coverage: scannerCoverage(out, report.policy.scope), provenance: { kind: 'untrusted SARIF import', sourceHash: sha256(data) }, }; } catch (error) { if (error instanceof CsoError) throw error; throw new CsoError('MISSING_INPUT', 'SARIF file is missing or unreadable'); } } else { event( report, `scanner-attempt:${id}`, 'Started bounded scanner collection; completion requires an immutable outcome artifact', ); saveReport(dir, report); record = await executeScanner({ id, runId: report.runId, runDir: dir, manifest: readJson(join(dir, 'snapshot.json')), policy: report.policy, executionDeadline: Date.parse(report.deadline) - 60_000, platform: platform(), request, watchdogPath: join(dirname(process.execPath), 'gstack-cso-watchdog'), }); } const outcome = record.outcome, originalCount = outcome.candidates.length; // Normalization can expand a 1 MiB scanner payload. Retain supported-size // candidate evidence and disclose omissions instead of saving unreadable state. while (Buffer.byteLength(JSON.stringify(record, null, 2)) > 950_000 && outcome.candidates.length) outcome.candidates.splice( Math.max(0, outcome.candidates.length - Math.max(1, Math.ceil(outcome.candidates.length / 4))), ); if (outcome.candidates.length < originalCount) { outcome.status = 'partial'; outcome.gaps.push({ code: 'OUTPUT_LIMIT', message: `${originalCount - outcome.candidates.length} scanner candidates withheld to fit the bounded immutable artifact`, }); record.coverage = scannerCoverage(outcome, report.policy.scope); } if (Buffer.byteLength(JSON.stringify(record, null, 2)) > 1024 * 1024) throw new CsoError( 'PERSISTENCE_FAILED', 'Scanner result exceeds the private artifact limit; no saved report is claimed', ); record = persistableArtifact(record, 'Scanner outcome'); const artifactId = `${outcome.tool}-${sha256(canonical(record)).slice(0, 16)}-${randomBytes(8).toString('hex')}`, file = join(dir, 'scanner-outcomes', `${artifactId}.json`); writeJsonExclusive(file, record); record.coverage.evidence.push(`Immutable outcome: ${artifactId}`); report.coverage.push(record.coverage); event( report, 'scanner-outcome', `${artifactId}: ${outcome.status}; ${outcome.candidates.length} candidates`, ); saveReport(dir, report); return { ...outcome, artifactId, artifact: `scanner-outcomes/${artifactId}.json`, provenance: record.provenance, }; }); } function scannerOutcome(args: string[]) { const { dir } = run(args); if (args.length !== 1 || !/^[a-z0-9-]{1,40}-[a-f0-9]{16}-[a-f0-9]{16}$/.test(args[0])) throw new CsoError('INVALID_ARGUMENT', 'scanner-outcome requires one immutable scanner artifact ID'); return readJson(join(dir, 'scanner-outcomes', `${args[0]}.json`)); } function recheckOriginalDirectory( repo: string, findingId: string, requestedRun?: string, ): { dir: string; runId: string } { const currentRepoId = repoId(repo), root = privateRoot(), repoDir = join(root, currentRepoId), runPattern = /^\d{13}-[a-f0-9]{16}$/; if (requestedRun) { if (!runPattern.test(requestedRun)) throw new CsoError('INVALID_ARGUMENT', 'Run identifier must be the ID returned by start'); const dir = join(repoDir, requestedRun); if (!fs.existsSync(dir)) throw new CsoError( 'MISSING_INPUT', 'Original run was not found for the current repository or has expired', ); return { dir: secureDirectory(dir), runId: requestedRun }; } if (!fs.existsSync(repoDir)) throw new CsoError( 'MISSING_INPUT', 'No finished original audit contains this finding in the current repository', ); const matches: { dir: string; runId: string }[] = [], directory = fs.opendirSync(secureDirectory(repoDir)); let visited = 0; try { let entry: fs.Dirent | null; while ((entry = directory.readSync()) !== null) { if (++visited > REPLAY_LOOKUP_MAX_ENTRIES) throw new CsoError( 'INSUFFICIENT_CAPACITY', `Recheck lookup exceeded ${REPLAY_LOOKUP_MAX_ENTRIES} private state entries`, ); if (!entry.isDirectory() || !runPattern.test(entry.name)) continue; const dir = join(repoDir, entry.name), reportPath = join(dir, 'report.json'); if (!fs.existsSync(reportPath)) continue; const report = loadReport(dir); if (report.runId !== entry.name || report.repoId !== currentRepoId) throw new CsoError( 'INCOMPATIBLE_INPUT', 'Retained original audit identity does not match its repository state path', ); if (report.status === 'finished' && !report.parent && report.findings.some((f) => f.id === findingId)) matches.push({ dir, runId: entry.name }); } } finally { directory.closeSync(); } if (!matches.length) throw new CsoError( 'MISSING_INPUT', 'No finished original audit contains this finding in the current repository', ); if (matches.length > 1) throw new CsoError( 'INVALID_ARGUMENT', `Finding matches ${matches.length} finished original audits; use --run RUN to select one`, ); return matches[0]; } async function recheck(args: string[], dependencies: CsoCliDependencies) { const startedAt = new Date(); if (!args.length) throw new CsoError('INVALID_ARGUMENT', 'recheck requires a finding ID'); const findingId = args.shift()!; if (!/^[a-f0-9]{32}$/.test(findingId)) throw new CsoError('INVALID_ARGUMENT', 'Finding identifier must be the 32-character ID reported by CSO'); const repo = callerPath(need(args, '--repo')), requestedRun = args.includes('--run') ? need(args, '--run') : undefined; if (args.length) throw new CsoError('INVALID_ARGUMENT', `Unknown recheck argument: ${args[0]}`); if (!fs.existsSync(repo) || !fs.statSync(repo).isDirectory()) throw new CsoError('MISSING_INPUT', 'Repository directory does not exist'); assertStateOutside(repo); retention(startedAt.getTime(), { deadlineMs: startedAt.getTime() + RETENTION_MAINTENANCE_MS, maxEntries: RETENTION_MAX_ENTRIES, }); const selected = recheckOriginalDirectory(repo, findingId, requestedRun), runId = selected.runId, originalDir = selected.dir; return await withLock(originalDir, async () => { const original = loadReport(originalDir); if (original.runId !== runId || original.repoId !== repoId(repo)) throw new CsoError( 'INCOMPATIBLE_INPUT', 'Retained original audit identity does not match its repository state path', ); const finding = original.findings.find((f) => f.id === findingId); if (!finding) throw new CsoError('MISSING_INPUT', 'Original finding does not exist'); if (original.status !== 'finished' || original.parent) throw new CsoError('INVALID_SCHEMA', 'Recheck requires a finished original audit'); // Keep the original immutable while the fresh snapshot is captured and // until its child lineage report has been durably published. const oldManifest = readJson(join(originalDir, 'snapshot.json')); const preserveBase = original.policy.diff || Boolean(original.source.baseCommit), report = await start( [ '--repo', repo, ...(original.policy.mode === 'comprehensive' ? ['--comprehensive'] : []), ...(original.policy.diff ? ['--diff'] : []), ...(preserveBase ? ['--base', original.policy.base] : []), '--budget', String(original.policy.budgetSeconds), ...(original.policy.offline ? ['--offline'] : []), ...(original.policy.scope === 'default' ? [] : original.policy.scope.startsWith('domain:') ? ['--scope', original.policy.scope.slice(7)] : [`--${original.policy.scope}`]), ], dependencies, { runId, findingId, kind: 'recheck' }, oldManifest.headCommit, startedAt, ); return { runId: report.runId, parent: report.parent }; }); } function recordReview(args: string[]) { const { dir } = run(args); if (!args.length) throw new CsoError('INVALID_ARGUMENT', 'record-review requires a request JSON file and --producer ID'); const raw = readInput(args.shift()!), producer = need(args, '--producer'); if (args.length) throw new CsoError('INVALID_ARGUMENT', `Unknown record-review argument: ${args[0]}`); const request = validateVerificationRequest(raw); return withLock(dir, () => { const report = loadReport(dir); requireTime(report); if ( report.policy.mode !== 'comprehensive' || report.status !== 'running' || !report.findings.some((f) => f.id === request.findingId && f.evidence === 'supported') ) throw new CsoError( 'MISSING_INPUT', 'Review artifact must target a supported finding in a running comprehensive audit', ); const artifact = persistableArtifact( makeReviewArtifact(report.runId, request, string(producer, 'producer identity', 200)), 'Repair review artifact', ); writeJsonExclusive(join(dir, 'reviews', `${artifact.id}.json`), artifact); event( report, 'repair-review', `Self-attested review artifact ${artifact.id} bound the proposed repair; reviewer independence is not host-verifiable`, ); saveReport(dir, report); return { reviewArtifactId: artifact.id, reviewAssurance: artifact.assurance, patchHash: artifact.patchHash, requestHash: artifact.requestHash, }; }); } function publicPlanArgument(manifest: SnapshotManifest, arg: string, paths: string[]): string { for (const path of [...paths].sort((a, b) => b.length - a.length)) { const reference = publicSnapshotPath(manifest, path).path; if (reference === path) continue; if (arg === path) return reference; if (arg === `./${path}`) return `./${reference}`; } return arg; } function publicTestPlan(manifest: SnapshotManifest, plan: ReturnType) { return { ...plan, commands: plan.commands.map((command) => ({ ...command, args: command.args.map((arg) => publicPlanArgument(manifest, arg, plan.files)), })), files: plan.files.map((path) => publicSnapshotPath(manifest, path).path), }; } function publicStartPlan(manifest: SnapshotManifest, plan: ReturnType) { return { ...plan, command: { ...plan.command, args: plan.command.args.map((arg) => publicPlanArgument(manifest, arg, plan.entrypointFiles)), }, entrypointFiles: plan.entrypointFiles.map((path) => publicSnapshotPath(manifest, path).path), }; } function testPlan(args: string[]) { const { dir } = run(args); if (args.length !== 1 || !['node', 'bun', 'python', 'rails'].includes(args[0])) throw new CsoError('INVALID_ARGUMENT', 'test-plan requires one supported stack'); const stack = args[0] as 'node' | 'bun' | 'python' | 'rails', manifest = readJson(join(dir, 'snapshot.json')) as SnapshotManifest; assertSnapshot(dir, manifest); const preparation = inspectPreparation(join(dir, 'snapshot'), stack); if (preparation.status !== 'ready') throw new CsoError( 'PREREQUISITE', preparation.prerequisites.map((item) => item.message).join('; ') || `${stack} preparation metadata is incomplete`, ); return { stack, runtimeProfile: preparation.runtimeProfile, ...publicTestPlan(manifest, canonicalTestPlan(join(dir, 'snapshot'), stack)), }; } function runtimePlan(args: string[]) { const { dir } = run(args); if (!args.length || !['node', 'bun', 'python', 'rails'].includes(args[0])) throw new CsoError('INVALID_ARGUMENT', 'runtime-plan requires one supported stack and --port PORT'); const stack = args.shift() as 'node' | 'bun' | 'python' | 'rails', rawPort = need(args, '--port'); if (args.length) throw new CsoError('INVALID_ARGUMENT', `Unknown runtime-plan argument: ${args[0]}`); const port = Number(rawPort); if (!Number.isInteger(port) || port < 1024 || port > 65535) throw new CsoError('INVALID_ARGUMENT', '--port must be an integer from 1024 to 65535'); const manifest = readJson(join(dir, 'snapshot.json')) as SnapshotManifest; assertSnapshot(dir, manifest); const preparation = inspectPreparation(join(dir, 'snapshot'), stack); if (preparation.status !== 'ready') throw new CsoError( 'PREREQUISITE', preparation.prerequisites.map((item) => item.message).join('; ') || `${stack} preparation metadata is incomplete`, ); return { stack, runtimeProfile: preparation.runtimeProfile, start: publicStartPlan(manifest, canonicalStartPlan(join(dir, 'snapshot'), stack, port)), tests: publicTestPlan(manifest, canonicalTestPlan(join(dir, 'snapshot'), stack)), }; } function platform(): 'linux/amd64' | 'linux/arm64' { if (!['linux', 'darwin'].includes(process.platform) || !['x64', 'arm64'].includes(process.arch)) throw new CsoError( 'PREREQUISITE', 'Contained target execution requires a Linux or macOS host with amd64/arm64 Linux Docker images', ); return process.arch === 'arm64' ? 'linux/arm64' : 'linux/amd64'; } function watchdog(): string { const p = join( dirname(process.execPath), process.platform === 'win32' ? 'gstack-cso-watchdog.exe' : 'gstack-cso-watchdog', ); if (!fs.existsSync(p)) throw new CsoError('ISOLATION_FAILED', 'Trusted detached watchdog is missing'); return p; } function closureStateFile(dir: string, findingId: string, phase: 'before' | 'after', plan: unknown): string { return join( dir, 'dependency-closures', `${findingId}-${phase}-${sha256(canonical(plan)).slice(0, 16)}.json`, ); } function retainClosure(path: string, closure: DependencyClosure): void { if (fs.existsSync(path)) { if (canonical(readJson(path)) !== canonical(closure)) throw new CsoError( 'INCOMPATIBLE_INPUT', 'Retained dependency closure conflicts with this preparation plan', ); return; } writeJsonExclusive(path, persistableArtifact(closure, 'Dependency closure')); } function bindArchiveHashes( target: string[], closures: { before: DependencyClosure; after: DependencyClosure }, ): void { const hashes = [ ...new Set([...closures.before.archives, ...closures.after.archives].map((archive) => archive.sha256)), ].sort(); target.splice(0, target.length, ...hashes); } function preparedVerificationExecutor(options: { dir: string; findingId: string; runtimeProfile: string; stack: 'node' | 'bun' | 'python' | 'rails'; targetPlatform: 'linux/amd64' | 'linux/arm64'; deadline: number; offline: boolean; runtimeCatalog: RuntimeCatalog; preparation: PreparationExecutor; delegate: VerificationExecutor; beforePlan: ReturnType; beforeAdmission: ReturnType; beforeClosure: DependencyClosure; closures: { before: DependencyClosure; after: DependencyClosure }; archiveHashes: string[]; proofs: { before: PreparationProof; after: PreparationProof }; replay?: { before: DependencyClosure; after: DependencyClosure }; persistClosures: boolean; }): VerificationExecutor { let beforeProjectToolchainHash: string | undefined; return { observe: async ( source, phase, request, runtime, verifier, work, control, _execution, testEvidence, witness, ) => { const plan = phase === 'before' ? options.beforePlan : inspectPreparation(source, options.stack); if (plan.status !== 'ready') throw new CsoError( 'PREREQUISITE', plan.prerequisites.map((item) => item.message).join('; ') || `${options.stack} dependency metadata is not ready`, ); const admission = phase === 'before' ? options.beforeAdmission : admitPreparationRuntime({ plan, platform: options.targetPlatform, profile: options.runtimeProfile, catalog: options.runtimeCatalog, }); if (admission.runtime.id !== runtime.id || admission.runtime.image !== runtime.image) throw new CsoError( 'INCOMPATIBLE_INPUT', 'Prepared verification runtime changed between source phases', ); const state = closureStateFile(options.dir, options.findingId, phase, plan), supplied = options.replay?.[phase], retained = !supplied && fs.existsSync(state) ? (readJson(state) as DependencyClosure) : undefined; const closure = phase === 'before' ? (supplied ?? options.beforeClosure) : await options.preparation.acquire({ plan, admission, snapshot: source, deadline: options.deadline, offline: options.offline || Boolean(supplied), existingClosure: supplied ?? retained, }); options.closures[phase] = closure; bindArchiveHashes(options.archiveHashes, options.closures); if (options.persistClosures) retainClosure(state, closure); let database: RailsDatabaseSelection | undefined; if (options.stack === 'rails') { const selected = plan.database?.selected; if (!selected) throw new CsoError( 'PREREQUISITE', 'Rails automatic verification could not select one locked database adapter from static test configuration', ); database = selected === 'postgresql' ? { adapter: 'postgresql', sidecar: admitPreparationSidecar({ platform: options.targetPlatform, catalog: options.runtimeCatalog, }), } : { adapter: 'sqlite' }; } const prepared = await options.preparation.prepareOffline({ plan, admission, snapshot: source, closure, deadline: options.deadline, database, }); try { options.proofs[phase] = { schemaVersion: 1, dependencyClosureHash: prepared.dependencyClosureHash, configurationHash: prepared.configurationHash, sourceProjectionHash: prepared.sourceProjectionHash, preparedManifestHash: prepared.preparedManifestHash, preparedDependencyHash: prepared.preparedDependencyHash, receiptHash: prepared.receiptHash, executionEnvironmentHash: sha256(canonical(prepared.executionEnvironment)), databaseHash: prepared.databaseHash, transformations: prepared.transformations, }; const sourceTests = canonicalTestPlan(source, options.stack), preparedTests = canonicalTestPlan(prepared.preparedRoot, options.stack), sourceStart = canonicalStartPlan(source, options.stack, request.port), preparedStart = canonicalStartPlan(prepared.preparedRoot, options.stack, request.port); if ( sourceTests.signature !== preparedTests.signature || sourceStart.signature !== preparedStart.signature || verificationHarnessHash(request, source) !== verificationHarnessHash(request, prepared.preparedRoot) ) throw new CsoError( 'ISOLATION_FAILED', 'Offline lifecycle execution changed the canonical start, test, or harness inputs', ); if (sourceTests.toolchain === 'project') { if (phase === 'before') beforeProjectToolchainHash = prepared.preparedDependencyHash; else if ( !beforeProjectToolchainHash || prepared.preparedDependencyHash !== beforeProjectToolchainHash ) throw new CsoError( 'ASSERTION_FAILED', 'Offline preparation changed the project-installed test toolchain between source phases', ); } const protectedPaths = new Set([ ...request.boundaryFiles, ...request.testFiles, ...sourceStart.entrypointFiles, ...request.changes.map((item) => item.path), ]); if (prepared.transformations.some((item) => protectedPaths.has(item.path))) throw new CsoError( 'ISOLATION_FAILED', 'Synthetic preparation transformation overlaps a security boundary, startup input, or test input', ); return await options.delegate.observe( prepared.preparedRoot, phase, request, runtime, verifier, work, control, { environment: prepared.executionEnvironment, database: prepared.database }, testEvidence, witness, ); } finally { await options.preparation.dispose(prepared); } }, }; } async function verify(args: string[], dependencies: CsoCliDependencies) { const { dir } = run(args); if (args.length !== 1) throw new CsoError('INVALID_ARGUMENT', 'verify requires one request JSON file'); const raw = readInput(args[0]), request = validateVerificationRequest(raw); return await withLock(dir, async () => { const report = loadReport(dir), manifest = readJson(join(dir, 'snapshot.json')) as SnapshotManifest; assertSnapshot(dir, manifest); requireTime(report); if (report.policy.mode !== 'comprehensive' || report.status !== 'running') throw new CsoError('INVALID_SCHEMA', 'Only a running comprehensive audit can request target execution'); const finding = report.findings.find((f) => f.id === request.findingId && f.evidence === 'supported'); if (!finding) throw new CsoError('MISSING_INPUT', 'Verification must target a supported finding in this run'); if (!request.review.artifactId) throw new CsoError( 'MISSING_INPUT', 'Verification requires a separately persisted independent repair-review artifact', ); const reviewArtifact = validateReviewArtifact( readJson(join(dir, 'reviews', `${request.review.artifactId}.json`)), report.runId, request, ); const findingPath = resolveSnapshotPath(manifest, finding.location.path, true, 'Finding path').path; if ( !request.boundaryFiles.some( (path) => resolveSnapshotPath(manifest, path, true, 'Boundary path').path === findingPath, ) ) throw new CsoError('INVALID_SCHEMA', 'Boundary files must include the finding location'); const attempts = report.events.filter((e) => e.kind === `verification-attempt:${finding.id}`).length; if (attempts >= 3) throw new CsoError( 'DEADLINE', 'Three bounded harness/repair attempts have already been used for this finding', ); if (report.findings.filter((f) => ['runtime_tested', 'tested'].includes(f.repair)).length >= 3) throw new CsoError('INSUFFICIENT_CAPACITY', 'This run already produced three runtime-tested repairs'); const targetPlatform = platform(); let runtime; try { runtime = selectRuntime(request.runtimeProfile, targetPlatform, dependencies.runtimeCatalog); } catch (error: any) { throw new CsoError('PREREQUISITE', error?.message || 'Qualified runtime is unavailable'); } const verifier = runtime; if (!['node', 'bun', 'python', 'rails'].includes(runtime.stack)) throw new CsoError( 'INCOMPATIBLE_INPUT', 'Application verification requires an application runtime profile', ); const plan = inspectPreparation(join(dir, 'snapshot'), runtime.stack as any); if (plan.status !== 'ready') throw new CsoError( 'PREREQUISITE', plan.prerequisites.map((p) => p.message).join('; ') || 'Runtime preparation metadata is incomplete', ); assertRuntimeCompatible(plan, runtime); writeJson(join(dir, `preparation-${runtime.stack}.json`), plan); const endpoint = await dockerEndpoint(secureDirectory(join(dir, 'home'))), watchdogPath = dependencies.watchdogPath(), attemptDeadline = Math.min(Date.now() + 300_000, Date.parse(report.deadline) - 60_000); const admission = admitPreparationRuntime({ plan, platform: targetPlatform, profile: runtime.id, catalog: dependencies.runtimeCatalog, }), staging = secureDirectory(join(dir, 'archive-staging')), runner = new DockerPreparationSandboxRunner({ endpoint, watchdogPath, runRoot: dir, controlRoot: secureDirectory(join(dir, 'preparation-execution')), admission, }), preparation = new PreparationExecutor({ cache: new PublicArchiveCache({ root: publicArchiveCacheRoot(), stagingRoot: staging }), runner, materializationRoot: secureDirectory(join(dir, 'archive-materializations')), }); const beforeState = closureStateFile(dir, finding.id, 'before', plan), retainedBefore = fs.existsSync(beforeState) ? (readJson(beforeState) as DependencyClosure) : undefined; const beforeClosure = await preparation.acquire({ plan, admission, snapshot: join(dir, 'snapshot'), deadline: attemptDeadline, offline: report.policy.offline, existingClosure: retainedBefore, }); retainClosure(beforeState, beforeClosure); const closures = { before: beforeClosure, after: beforeClosure }, archiveHashes = [...new Set(beforeClosure.archives.map((archive) => archive.sha256))].sort(), proofs = {} as { before: PreparationProof; after: PreparationProof }, delegate = new DockerVerificationExecutor(endpoint, watchdogPath, attemptDeadline, () => { event( report, `verification-attempt:${finding.id}`, `Started bounded repair verification attempt ${attempts + 1}`, ); saveReport(dir, report); }); const executor = preparedVerificationExecutor({ dir, findingId: finding.id, runtimeProfile: runtime.id, stack: runtime.stack as 'node' | 'bun' | 'python' | 'rails', targetPlatform, deadline: attemptDeadline, offline: report.policy.offline, runtimeCatalog: dependencies.runtimeCatalog, preparation, delegate, beforePlan: plan, beforeAdmission: admission, beforeClosure, closures, archiveHashes, proofs, persistClosures: true, }); let result: Awaited>; try { result = await verifyRepair({ runId: report.runId, runDir: dir, manifest, rawRequest: raw, runtime, verifier, policyHash: ISOLATION_POLICY_HASH, auditPolicyHash: sha256(canonical(report.policy)), archives: archiveHashes, dependencyClosures: closures, preparation: proofs, reviewArtifact, executor, watchdogPath, attemptDeadline, }); } catch (error) { if (error instanceof VerificationAttemptError) { finding.reproduction = error.attempt.reproduction; finding.repair = error.attempt.repair; finding.reproductionAttemptId = error.attempt.id; event( report, error.attempt.repair === 'proposed' ? 'repair-candidate' : 'verification-failed', error.attempt.repair === 'proposed' ? `${error.attempt.id}: external repair assertions passed; helper-authenticated external assertion witness required before certification` : `${error.attempt.id}: ${error.attempt.reproduction}; repair validation failed without issuing a bundle`, ); saveReport(dir, report); } throw error; } finding.reproduction = result.manifest.before.security === 'intended_failure' && result.manifest.before.booted && result.manifest.before.legitimate ? 'reproduced' : result.manifest.before.security === 'pass' ? 'disproved' : result.manifest.before.booted ? 'inconclusive' : 'blocked'; finding.repair = result.manifest.result === 'tested' ? 'tested' : result.manifest.result === 'runtime_tested' ? 'runtime_tested' : 'failed'; if (['tested', 'runtime_tested'].includes(result.manifest.result)) { finding.verificationId = result.manifest.id; finding.verificationAssurance = { assertions: result.manifest.assertionAssurance!, testCompletion: result.manifest.testCompletionAssurance, review: result.manifest.reviewAssurance, }; delete finding.reproductionAttemptId; } event( report, 'verification', `${result.manifest.id}: ${result.manifest.result}; assertion assurance ${result.manifest.assertionAssurance}; test completion assurance ${result.manifest.testCompletionAssurance}; review assurance ${result.manifest.reviewAssurance}`, ); saveReport(dir, report); return { result: result.manifest.result, verification: result.manifest, bundle: `bundles/${result.bundle.id}.json`, }; }); } function replayBundle(stored: { path: string; dir: string }, id: string): any { const bundle = validateRepairBundle(readJson(stored.path), id), report = loadReport(stored.dir), finding = report.findings.find( (f) => f.verificationId === id && ['tested', 'runtime_tested'].includes(f.repair), ); if (!['tested', 'runtime_tested'].includes(bundle.verification.result) || !finding) throw new CsoError( 'INCOMPATIBLE_INPUT', 'Only a helper-recorded runtime-tested or host-reviewed repair bundle can be replayed', ); return bundle; } async function withReplayBundle( id: string, deadline: number, fn: (stored: { path: string; dir: string }, bundle: any) => Promise, ): Promise { if (!/^[a-f0-9]{32}$/.test(id)) throw new CsoError( 'INVALID_ARGUMENT', 'Bundle identifier must be the 32-character ID returned by verify', ); let visited = 0, stored: { path: string; dir: string } | undefined; const admit = () => { if (Date.now() >= deadline) throw new CsoError( 'DEADLINE', 'Replay exhausted its five-minute budget while locating the recorded bundle', ); if (++visited > REPLAY_LOOKUP_MAX_ENTRIES) throw new CsoError( 'INSUFFICIENT_CAPACITY', `Replay bundle lookup exceeded ${REPLAY_LOOKUP_MAX_ENTRIES} private state entries`, ); }; const root = privateRoot(), repos = fs.opendirSync(root); try { let repo: fs.Dirent | null; search: while ((repo = repos.readSync()) !== null) { admit(); if (!repo.isDirectory() || !/^[a-f0-9]{24}$/.test(repo.name)) continue; const repoDir = join(root, repo.name), runs = fs.opendirSync(repoDir); try { let run: fs.Dirent | null; while ((run = runs.readSync()) !== null) { admit(); if (!run.isDirectory() || !/^\d{13}-[a-f0-9]{16}$/.test(run.name)) continue; const candidate = { dir: join(repoDir, run.name), path: join(repoDir, run.name, 'bundles', `${id}.json`), }; if (fs.existsSync(candidate.path)) { stored = candidate; break search; } } } finally { runs.closeSync(); } } } finally { repos.closeSync(); } if (!stored) throw new CsoError('MISSING_INPUT', 'Repair bundle was not found or expired'); let matched = false, value!: T; await withLock(stored.dir, async () => { if (!fs.existsSync(stored!.path)) return; const bundle = replayBundle(stored!, id); matched = true; value = await fn(stored!, bundle); }); if (matched) return value; throw new CsoError('MISSING_INPUT', 'Repair bundle was not found or expired'); } function replayManifestValue(manifest: any): unknown { const { id: _, createdAt: __, witnessHash: ___, before, after, ...stable } = manifest, observation = (value: any) => { const { output: _, ...rest } = value; return rest; }; return { ...stable, before: observation(before), after: observation(after) }; } async function replay(args: string[], dependencies: CsoCliDependencies) { const replayStarted = Date.now(), replayDeadline = replayStarted + 300_000; retention(replayStarted, { deadlineMs: replayStarted + RETENTION_MAINTENANCE_MS, maxEntries: RETENTION_MAX_ENTRIES, }); if (!args.length) throw new CsoError('INVALID_ARGUMENT', 'replay requires a bundle ID'); const id = args.shift()!, source = args.includes('--source') ? callerPath(need(args, '--source')) : undefined; if (args.length) throw new CsoError('INVALID_ARGUMENT', `Unknown replay argument: ${args[0]}`); return await withReplayBundle(id, replayDeadline, async (stored, bundle) => { if (bundle.requiredInputs.archives?.length && !bundle.requiredInputs.dependencyClosures) throw new CsoError( 'MISSING_INPUT', 'Replay bundle predates retained dependency closures and cannot substitute current dependency state', ); let workDir = stored.dir, manifest: any, temporary: string | undefined; const retained = join(stored.dir, 'snapshot'); try { const captureSupplied = async () => { if (!source) throw new CsoError('MISSING_INPUT', 'Retained source expired; supply explicitly matching source'); const temp = newRun(source); temporary = temp.dir; workDir = temp.dir; manifest = await capture(source, workDir, undefined, undefined, { deadlineMs: replayDeadline }); if ( manifest.executionHash !== bundle.requiredInputs.sourceHash || manifest.originalHash !== bundle.requiredInputs.originalHash ) throw new CsoError('INCOMPATIBLE_INPUT', 'Supplied source does not match the bundle input hashes'); }; if (fs.existsSync(retained)) { manifest = readJson(join(stored.dir, 'snapshot.json')); const expiresAt = typeof manifest?.expiresAt === 'string' ? Date.parse(manifest.expiresAt) : Number.NaN; if (!Number.isFinite(expiresAt) || new Date(expiresAt).toISOString() !== manifest.expiresAt) throw new CsoError('INCOMPATIBLE_INPUT', 'Retained snapshot expiry is invalid'); if (expiresAt <= Date.now()) await captureSupplied(); else assertSnapshot(stored.dir, manifest); } else await captureSupplied(); if ( manifest.executionHash !== bundle.requiredInputs.sourceHash || manifest.originalHash !== bundle.requiredInputs.originalHash ) throw new CsoError('INCOMPATIBLE_INPUT', 'Retained source hashes do not match the bundle'); validateRepairBundle(bundle, id, join(workDir, 'snapshot'), manifest); if (bundle.verification.policyHash !== ISOLATION_POLICY_HASH) throw new CsoError( 'INCOMPATIBLE_INPUT', 'Current helper isolation policy does not match the recorded bundle', ); const targetPlatform = bundle.requiredInputs.platform as 'linux/amd64' | 'linux/arm64'; let runtime; try { runtime = selectRuntime( bundle.verification.runtime.profile, targetPlatform, dependencies.runtimeCatalog, ); } catch (error: any) { throw new CsoError('PREREQUISITE', error?.message || 'Qualified replay runtime is unavailable'); } const verifier = runtime; if (runtime.image !== bundle.requiredInputs.runtimeImage) throw new CsoError('INCOMPATIBLE_INPUT', 'Qualified runtime digest does not match the bundle'); const endpoint = await dockerEndpoint(secureDirectory(join(workDir, 'home'))), watchdogPath = dependencies.watchdogPath(), attemptDeadline = replayDeadline, delegate = new DockerVerificationExecutor(endpoint, watchdogPath, attemptDeadline); let executor: VerificationExecutor = delegate, archives: string[] = [], dependencyClosures: { before: DependencyClosure; after: DependencyClosure } | undefined, proofs: { before: PreparationProof; after: PreparationProof } | undefined; if (bundle.requiredInputs.dependencyClosures) { if (!['node', 'bun', 'python', 'rails'].includes(runtime.stack)) throw new CsoError( 'INCOMPATIBLE_INPUT', 'Replay dependency closure requires an application runtime', ); const replayClosures = bundle.requiredInputs.dependencyClosures as { before: DependencyClosure; after: DependencyClosure; }, plan = inspectPreparation(join(workDir, 'snapshot'), runtime.stack as any); if (plan.status !== 'ready') throw new CsoError( 'PREREQUISITE', plan.prerequisites.map((item: any) => item.message).join('; ') || 'Replay dependency metadata is not ready', ); const admission = admitPreparationRuntime({ plan, platform: targetPlatform, profile: runtime.id, catalog: dependencies.runtimeCatalog, }), runner = new DockerPreparationSandboxRunner({ endpoint, watchdogPath, runRoot: workDir, controlRoot: secureDirectory(join(workDir, 'preparation-execution')), admission, }), preparation = new PreparationExecutor({ cache: new PublicArchiveCache({ root: publicArchiveCacheRoot(), stagingRoot: secureDirectory(join(workDir, 'archive-staging')), }), runner, materializationRoot: secureDirectory(join(workDir, 'archive-materializations')), }), beforeClosure = await preparation.acquire({ plan, admission, snapshot: join(workDir, 'snapshot'), deadline: attemptDeadline, offline: true, existingClosure: replayClosures.before, }); dependencyClosures = { before: beforeClosure, after: replayClosures.after }; archives = [ ...new Set( [...beforeClosure.archives, ...replayClosures.after.archives].map((archive) => archive.sha256), ), ].sort(); proofs = {} as { before: PreparationProof; after: PreparationProof }; executor = preparedVerificationExecutor({ dir: workDir, findingId: bundle.request.findingId, runtimeProfile: runtime.id, stack: runtime.stack as any, targetPlatform, deadline: attemptDeadline, offline: true, runtimeCatalog: dependencies.runtimeCatalog, preparation, delegate, beforePlan: plan, beforeAdmission: admission, beforeClosure, closures: dependencyClosures, archiveHashes: archives, proofs, replay: replayClosures, persistClosures: false, }); } const result = await verifyRepair({ runId: bundle.runId, runDir: workDir, manifest, rawRequest: bundle.request, runtime, verifier, policyHash: ISOLATION_POLICY_HASH, auditPolicyHash: bundle.verification.auditPolicyHash, archives, dependencyClosures, preparation: proofs, reviewArtifact: bundle.reviewArtifact, executor, persist: false, watchdogPath, attemptDeadline, }); if ( canonical(replayManifestValue(result.manifest)) !== canonical(replayManifestValue(bundle.verification)) || assertionWitnessReplayHash(result.bundle.witness!) !== assertionWitnessReplayHash(bundle.witness) ) throw new CsoError( 'INCOMPATIBLE_INPUT', 'Replay changed verification outcomes, preparation, or provenance inputs', ); const replayId = `${Date.now()}-${randomBytes(8).toString('hex')}`; writeJsonExclusive(join(stored.dir, 'replays', `${replayId}.json`), { replayId, bundleId: id, verification: result.manifest, witness: result.bundle.witness, }); return { bundle: id, result: result.manifest.result, replay: result.manifest, replayId }; } finally { if (temporary) finalizeReplayTemporary(temporary); } }); } export async function dispatchCsoCommand( command: string, args: string[], dependencies: CsoCliDependencies, ): Promise { args = [...args]; if (!['start', 'recheck', 'replay', 'doctor', 'provision-images'].includes(command)) { const started = Date.now(); retention(started, { deadlineMs: started + RETENTION_MAINTENANCE_MS, maxEntries: RETENTION_MAX_ENTRIES }); } let result: unknown; switch (command) { case 'start': result = await start(args, dependencies); break; case 'doctor': result = await doctor(args, dependencies); break; case 'provision-images': result = await provisionImages(args, dependencies); break; case 'resume': result = resume(args); break; case 'inspect': await inspect(args); return; case 'read': await read(args); return; case 'history': await history(args); return; case 'submit': result = submit(args); break; case 'finish': result = finish(args); break; case 'import-v2': result = importV2(args); break; case 'inspect-v2': result = inspectV2(args); break; case 'scan': result = await scanner(args); break; case 'scanner-outcome': result = scannerOutcome(args); break; case 'import-sarif': result = await scanner(args, true); break; case 'record-review': result = recordReview(args); break; case 'test-plan': result = testPlan(args); break; case 'runtime-plan': result = runtimePlan(args); break; case 'recheck': result = await recheck(args, dependencies); break; case 'verify': result = await verify(args, dependencies); break; case 'replay': result = await replay(args, dependencies); break; case 'patch-hash': if (args.length !== 1) throw new CsoError('INVALID_ARGUMENT', 'patch-hash requires one request JSON file'); result = { patchHash: patchHash(validateVerificationRequest(readInput(args[0]))) }; break; default: throw new CsoError('INVALID_ARGUMENT', `Unknown command: ${command}`); } return result; } const PRODUCTION_CLI_DEPENDENCIES: CsoCliDependencies = Object.freeze({ runtimeCatalog: RUNTIME_CATALOG, scannerCatalog: SCANNER_CATALOG, catalogImageSession: productionCatalogImageSession, watchdogPath: watchdog, }); async function main() { const args = process.argv.slice(2), command = args.shift(); if (!command || command === '--help' || command === 'help') { process.stdout.write(HELP + '\n'); return; } if (command === '--version') { emit({ version: VERSION, abi: ABI }); return; } if (command === 'schema') { emit(SCHEMA); return; } if (command === '__cso-assertion-witness') { if (args.length) throw new CsoError('INVALID_ARGUMENT', 'Assertion witness does not accept command arguments'); await runAssertionWitnessChild(); return; } const result = await dispatchCsoCommand(command, args, PRODUCTION_CLI_DEPENDENCIES); if (result !== undefined) emit(result); } if (import.meta.main) main().catch((error) => { const e = error instanceof CsoError ? error : new CsoError('INVALID_SCHEMA', 'The helper rejected an unexpected or unsafe input'); try { process.stderr.write( redact(JSON.stringify({ ok: false, error: { code: e.code, message: e.message } })) + '\n', ); } catch { process.stderr.write( '{"ok":false,"error":{"code":"REDACTION_FAILED","message":"Error payload withheld"}}\n', ); } process.exitCode = 1; });