@@ -28,6 +28,8 @@ interface TrustAnchor {
2828const anchors = new Map < string , TrustAnchor > ( ) ; // keyed by origin_id hex
2929
3030// Checkpoint cache: "origin:treeSize" → rootHash
31+ // Bounded to prevent memory exhaustion from payloads with incrementing tree_size.
32+ const MAX_CACHE_ENTRIES = 1000 ;
3133const checkpointCache = new Map < string , { rootHash : Uint8Array ; fetchedAt : number } > ( ) ;
3234
3335// --- Verification ---
@@ -104,6 +106,9 @@ async function verify(payloadBytes: Uint8Array): Promise<VerifyResult> {
104106 add ( "Checkpoint fetch+verify" , true ,
105107 `issuer sig ✓ · ${ anchor . witnessQuorum } /${ anchor . witnessQuorum } witnesses ✓ · tree_size=${ fetchedSize } ` ) ;
106108 rootHash = fetchedRoot ;
109+ if ( checkpointCache . size >= MAX_CACHE_ENTRIES ) {
110+ checkpointCache . delete ( checkpointCache . keys ( ) . next ( ) . value ! ) ;
111+ }
107112 checkpointCache . set ( cacheKey , { rootHash : fetchedRoot , fetchedAt : Date . now ( ) } ) ;
108113 }
109114
@@ -296,10 +301,18 @@ const server = createServer(async (req, res) => {
296301 keyID : new Uint8Array ( Buffer . from ( w . key_id_hex , "hex" ) ) ,
297302 pubKey : new Uint8Array ( Buffer . from ( w . pub_key_hex , "hex" ) ) ,
298303 } ) ) ;
304+ const witnessQuorum = tc . witness_quorum ;
305+ if ( ! Number . isInteger ( witnessQuorum ) || witnessQuorum < 1 ) {
306+ return json ( res , { ok : false , error : `witness_quorum must be >= 1, got ${ witnessQuorum } ` } , 400 ) ;
307+ }
308+ if ( witnessQuorum > witnesses . length ) {
309+ return json ( res , { ok : false ,
310+ error : `witness_quorum (${ witnessQuorum } ) exceeds witness count (${ witnesses . length } )` } , 400 ) ;
311+ }
299312 const anchor : TrustAnchor = {
300313 origin : tc . origin , originID : oid , issuerPubKey,
301314 issuerKeyName : tc . issuer_key_name ?? "" ,
302- sigAlg : tc . sig_alg , witnessQuorum : tc . witness_quorum ,
315+ sigAlg : tc . sig_alg , witnessQuorum,
303316 witnesses, checkpointURL : tc . checkpoint_url ,
304317 } ;
305318 anchors . set ( oid . toString ( 16 ) . padStart ( 16 , "0" ) , anchor ) ;
0 commit comments