@@ -271,5 +271,84 @@ describe('peers', () => {
271271 expect ( peer . dcOpen ) . toBe ( false ) ;
272272 expect ( peer . packAndSend ) . toBeUndefined ( ) ;
273273 } ) ;
274+
275+ describe ( 'JSON parsing security (CVE-HSYNC-2026-005)' , ( ) => {
276+ it ( 'should handle invalid JSON in transport.receiveData without crashing' , ( ) => {
277+ const peer = peerLib . createRPCPeer ( { hostName : 'other.example.com' } ) ;
278+
279+ // Should not throw on invalid JSON
280+ expect ( ( ) => {
281+ peer . transport . receiveData ( 'not valid json {{{' ) ;
282+ } ) . not . toThrow ( ) ;
283+ } ) ;
284+
285+ it ( 'should handle empty string in transport.receiveData' , ( ) => {
286+ const peer = peerLib . createRPCPeer ( { hostName : 'other.example.com' } ) ;
287+
288+ // Empty string should not throw
289+ expect ( ( ) => {
290+ peer . transport . receiveData ( '' ) ;
291+ } ) . not . toThrow ( ) ;
292+ } ) ;
293+
294+ it ( 'should handle malformed JSON payloads gracefully' , ( ) => {
295+ const peer = peerLib . createRPCPeer ( { hostName : 'other.example.com' } ) ;
296+
297+ // Various malformed inputs - should not crash
298+ const malformedInputs = [ '{"unclosed": ' , '[1, 2, 3' , 'undefined' , 'NaN' ] ;
299+
300+ for ( const input of malformedInputs ) {
301+ expect ( ( ) => {
302+ peer . transport . receiveData ( input ) ;
303+ } ) . not . toThrow ( ) ;
304+ }
305+ } ) ;
306+
307+ it ( 'should reject non-object JSON values' , ( ) => {
308+ const peer = peerLib . createRPCPeer ( { hostName : 'other.example.com' } ) ;
309+
310+ // Valid JSON but not objects - should not crash
311+ const nonObjectInputs = [ '"just a string"' , '123' , 'true' , 'null' ] ;
312+
313+ for ( const input of nonObjectInputs ) {
314+ expect ( ( ) => {
315+ peer . transport . receiveData ( input ) ;
316+ } ) . not . toThrow ( ) ;
317+ }
318+ } ) ;
319+
320+ it ( 'should process valid JSON normally' , ( ) => {
321+ const peer = peerLib . createRPCPeer ( { hostName : 'other.example.com' } ) ;
322+ const rpcEmitSpy = vi . spyOn ( peer . transport , 'emit' ) ;
323+
324+ const validMsg = JSON . stringify ( { method : 'test' , params : [ ] } ) ;
325+ peer . transport . receiveData ( validMsg ) ;
326+
327+ expect ( rpcEmitSpy ) . toHaveBeenCalledWith ( 'rpc' , expect . objectContaining ( { method : 'test' } ) ) ;
328+ } ) ;
329+
330+ it ( 'should handle invalid JSON in server peer transport' , ( ) => {
331+ const serverPeer = peerLib . createServerPeer ( ) ;
332+
333+ // Should not throw on invalid JSON
334+ expect ( ( ) => {
335+ serverPeer . transport . receiveData ( 'invalid json' ) ;
336+ } ) . not . toThrow ( ) ;
337+ } ) ;
338+
339+ it ( 'should handle null/undefined in server peer transport' , ( ) => {
340+ const serverPeer = peerLib . createServerPeer ( ) ;
341+
342+ // Null should not throw
343+ expect ( ( ) => {
344+ serverPeer . transport . receiveData ( null ) ;
345+ } ) . not . toThrow ( ) ;
346+
347+ // Undefined should not throw
348+ expect ( ( ) => {
349+ serverPeer . transport . receiveData ( undefined ) ;
350+ } ) . not . toThrow ( ) ;
351+ } ) ;
352+ } ) ;
274353 } ) ;
275354} ) ;
0 commit comments