@@ -21,11 +21,15 @@ export class DropInStorage {
2121 this . ourIdentityKeyPair = identity ?? generateIdentityKeyPair ( ) ;
2222 this . ourRegistrationId = regId ?? generateRegistrationId ( ) ;
2323 }
24+ // Clone on both boundaries so the in-memory map behaves like real on-disk
25+ // (serialized) persistence: a caller can't mutate stored state without an
26+ // explicit store, and a stored object can't be changed after the fact.
2427 async loadSession ( address : string ) {
25- return this . sessions . get ( address ) ; // the libsignal-node JSON object, as stored
28+ const s = this . sessions . get ( address ) ; // the libsignal-node JSON object, as stored
29+ return s === undefined ? undefined : structuredClone ( s ) ;
2630 }
2731 async storeSession ( address : string , session : any ) {
28- this . sessions . set ( address , session ) ;
32+ this . sessions . set ( address , structuredClone ( session ) ) ;
2933 }
3034 // intentionally no storeSessionRaw → drop-in (JSON) mode for sessions + sender keys
3135 async loadSenderKey ( id : string ) {
@@ -40,6 +44,9 @@ export class DropInStorage {
4044 async getOurRegistrationId ( ) {
4145 return this . ourRegistrationId ;
4246 }
47+ // libsignal `SignalStorage` interface method (the bridge's SessionCipher calls
48+ // it). TOFU: registers the identity on first sight (an intentional setup side
49+ // effect), then verifies equality thereafter.
4350 async isTrustedIdentity ( id : string , key : Uint8Array ) {
4451 const e = this . identities . get ( id ) ;
4552 if ( ! e ) {
0 commit comments