peer-term 1.2.11 → 1.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +69 -17
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peer-term",
3
- "version": "1.2.11",
3
+ "version": "1.2.12",
4
4
  "license": "MIT",
5
5
  "description": "Share your terminal instantly using a 6-digit code. Encrypted. No config.",
6
6
  "keywords": [
package/src/index.js CHANGED
@@ -368,25 +368,54 @@ class Session {
368
368
 
369
369
  async _completeKeyExchange(clientPublicKeyBase64) {
370
370
  if (!this.keyPair || !this.hostPublicKeyBase64) return;
371
+ if (typeof clientPublicKeyBase64 !== 'string' || clientPublicKeyBase64.length === 0) {
372
+ this._rejectProtocolMessage('Invalid key-exchange public key');
373
+ return;
374
+ }
371
375
 
372
- this.logDebug('Deriving shared secret...');
373
- this.clientPublicKeyBase64 = clientPublicKeyBase64;
376
+ try {
377
+ this.logDebug('Deriving shared secret...');
378
+ this.clientPublicKeyBase64 = clientPublicKeyBase64;
379
+
380
+ const peerPublicKey = await importPublicKey(clientPublicKeyBase64);
381
+ this.sharedKey = await deriveSharedKey(this.keyPair.privateKey, peerPublicKey);
382
+
383
+ if (this.secureMode) {
384
+ this.securityFingerprint = await fingerprintPublicKeys(
385
+ this.code,
386
+ this.hostPublicKeyBase64,
387
+ this.clientPublicKeyBase64
388
+ );
389
+ this.fingerprintAuthorized = false;
390
+ this._printFingerprintAuthorization();
391
+ } else {
392
+ this.fingerprintAuthorized = true;
393
+ await this._activateSecureSession();
394
+ }
395
+ } catch (err) {
396
+ this._rejectProtocolMessage(`Invalid key exchange: ${err.message}`);
397
+ }
398
+ }
374
399
 
375
- const peerPublicKey = await importPublicKey(clientPublicKeyBase64);
376
- this.sharedKey = await deriveSharedKey(this.keyPair.privateKey, peerPublicKey);
400
+ _rejectProtocolMessage(reason) {
401
+ this.log(`Protocol error: ${reason}`);
402
+ this.isClientConnected = false;
403
+ this.awaitingRejoin = false;
404
+ this.sharedKey = null;
405
+ this.keyPair = null;
406
+ this.hostPublicKeyBase64 = null;
407
+ this.clientPublicKeyBase64 = null;
408
+ this.securityFingerprint = null;
409
+ this.fingerprintAuthorized = false;
410
+ this.stopHeartbeat();
411
+ this._cleanupWebRTC();
412
+ this.destroy();
413
+ }
377
414
 
378
- if (this.secureMode) {
379
- this.securityFingerprint = await fingerprintPublicKeys(
380
- this.code,
381
- this.hostPublicKeyBase64,
382
- this.clientPublicKeyBase64
383
- );
384
- this.fingerprintAuthorized = false;
385
- this._printFingerprintAuthorization();
386
- } else {
387
- this.fingerprintAuthorized = true;
388
- await this._activateSecureSession();
389
- }
415
+ _handleMessageError(err) {
416
+ const message = err instanceof Error ? err.message : String(err);
417
+ this.log(`Protocol handler error: ${message}`);
418
+ this.destroy();
390
419
  }
391
420
 
392
421
  _printFingerprintAuthorization() {
@@ -481,6 +510,7 @@ class Session {
481
510
  });
482
511
 
483
512
  this.ws.on('message', async (raw) => {
513
+ try {
484
514
  let msg;
485
515
  try {
486
516
  msg = JSON.parse(raw.toString());
@@ -488,6 +518,10 @@ class Session {
488
518
  this.log('Invalid message from relay');
489
519
  return;
490
520
  }
521
+ if (!msg || typeof msg.type !== 'string') {
522
+ this._rejectProtocolMessage('Malformed relay message');
523
+ return;
524
+ }
491
525
 
492
526
  switch (msg.type) {
493
527
  case 'code': {
@@ -614,6 +648,9 @@ class Session {
614
648
  break;
615
649
  }
616
650
  }
651
+ } catch (err) {
652
+ this._handleMessageError(err);
653
+ }
617
654
  });
618
655
 
619
656
  this.ws.on('close', () => {
@@ -910,12 +947,17 @@ class Session {
910
947
  });
911
948
 
912
949
  newWs.on('message', async (raw) => {
950
+ try {
913
951
  let msg;
914
952
  try {
915
953
  msg = JSON.parse(raw.toString());
916
954
  } catch {
917
955
  return;
918
956
  }
957
+ if (!msg || typeof msg.type !== 'string') {
958
+ this._rejectProtocolMessage('Malformed relay message');
959
+ return;
960
+ }
919
961
 
920
962
  if (msg.type === 'rejoined') {
921
963
  // Success — replace the old ws with this new one
@@ -935,6 +977,9 @@ class Session {
935
977
  this.destroy();
936
978
  try { newWs.close(); } catch {}
937
979
  }
980
+ } catch (err) {
981
+ this._handleMessageError(err);
982
+ }
938
983
  });
939
984
 
940
985
  newWs.on('error', () => {
@@ -970,6 +1015,7 @@ class Session {
970
1015
  */
971
1016
  _attachWsHandlers(newWs) {
972
1017
  newWs.on('message', async (raw) => {
1018
+ try {
973
1019
  let msg;
974
1020
  try {
975
1021
  msg = JSON.parse(raw.toString());
@@ -977,6 +1023,10 @@ class Session {
977
1023
  this.log('Invalid message from relay');
978
1024
  return;
979
1025
  }
1026
+ if (!msg || typeof msg.type !== 'string') {
1027
+ this._rejectProtocolMessage('Malformed relay message');
1028
+ return;
1029
+ }
980
1030
 
981
1031
  switch (msg.type) {
982
1032
  case 'client-connected': {
@@ -1084,6 +1134,9 @@ class Session {
1084
1134
  break;
1085
1135
  }
1086
1136
  }
1137
+ } catch (err) {
1138
+ this._handleMessageError(err);
1139
+ }
1087
1140
  });
1088
1141
 
1089
1142
  newWs.on('close', () => {
@@ -1414,7 +1467,6 @@ process.on('uncaughtException', (err) => {
1414
1467
  process.on('unhandledRejection', (reason) => {
1415
1468
  const err = reason instanceof Error ? reason : new Error(String(reason));
1416
1469
  logger.error(`Unhandled rejection: ${err.message}`, err);
1417
- process.exit(1);
1418
1470
  });
1419
1471
 
1420
1472
  // ─── Run ─────────────────────────────────────────────────────────────────────