Skill Tracer
Skills › gstack › gstack › cso-attestation-evidence.ts

cso-attestation-evidence.ts

29 lines · scripts/cso-attestation-evidence.ts at 3f79d81

1#!/usr/bin/env -S bun --no-env-file --config=/dev/null
2/** Bind cryptographically verified `gh attestation verify --format json` output to reviewed statements. */
3import * as fs from 'node:fs';
4import { resolve } from 'node:path';
5import { canonical, sha256 } from '../lib/cso/contracts';
6
7const HASH=/^[a-f0-9]{64}$/,MAX_BYTES=4*1024*1024;
8
9export function verifiedStatementSetDigest(value:unknown,predicateType:string,subjectSha256:string):string{
10 if(!Array.isArray(value)||!value.length||typeof predicateType!=='string'||!/^https:\/\/[A-Za-z0-9./_-]+$/.test(predicateType)||!HASH.test(subjectSha256))throw new Error('INVALID_VERIFIED_ATTESTATION_SET');
11 const statements:string[]=[];
12 for(const item of value){
13 if(!item||typeof item!=='object'||Array.isArray(item))throw new Error('INVALID_VERIFIED_ATTESTATION_SET');
14 const result=(item as any).verificationResult,statement=result?.statement;
15 if(!statement||typeof statement!=='object'||Array.isArray(statement)||statement.predicateType!==predicateType||!Array.isArray(statement.subject)||
16 !statement.subject.some((subject:any)=>subject&&typeof subject==='object'&&subject.digest?.sha256===subjectSha256))throw new Error('VERIFIED_ATTESTATION_IDENTITY_MISMATCH');
17 statements.push(canonical(statement));
18 }
19 statements.sort();return`sha256:${sha256(canonical(statements))}`;
22if(import.meta.main){
23 try{
24 const args=process.argv.slice(2),command=args.shift(),file=args.shift(),predicate=args.shift(),subject=args.shift();
25 if(command!=='digest'||!file||!predicate||!subject||args.length)throw new Error('Usage: cso-attestation-evidence digest VERIFIED.json PREDICATE SUBJECT_SHA256');
26 const path=resolve(file),stat=fs.lstatSync(path);if(!stat.isFile()||stat.isSymbolicLink()||stat.nlink!==1||stat.size<=0||stat.size>MAX_BYTES)throw new Error('UNSAFE_VERIFIED_ATTESTATION_FILE');
27 process.stdout.write(verifiedStatementSetDigest(JSON.parse(fs.readFileSync(path,'utf8')),predicate,subject)+'\n');
28 }catch(error){process.stderr.write((error instanceof Error?error.message:'ATTESTATION_EVIDENCE_ERROR')+'\n');process.exitCode=1;}