@slicedearth/whoisleuth-cli 2.4.0 → 2.5.1

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 (300) hide show
  1. package/NOTICE +2 -2
  2. package/cli/argument-values.mjs +55 -0
  3. package/cli/arguments.mjs +24 -470
  4. package/cli/artifact-validation/case-response.mjs +21 -6
  5. package/cli/artifact-validation/lookup-evidence.mjs +3 -3
  6. package/cli/artifact-validation/signed-review.mjs +59 -13
  7. package/cli/artifact-verify.mjs +2 -0
  8. package/cli/assurance-arguments.mjs +56 -0
  9. package/cli/assurance-command-definitions.mjs +179 -0
  10. package/cli/assurance-command-runner.mjs +1 -1
  11. package/cli/bounded-json.mjs +1 -1
  12. package/cli/bulk-checkpoint.mjs +1 -1
  13. package/cli/bulk-command-runner.mjs +2 -2
  14. package/cli/bulk.mjs +2 -3
  15. package/cli/case-command.mjs +20 -3
  16. package/cli/case-pack.mjs +12 -2
  17. package/cli/ci-report.mjs +6 -3
  18. package/cli/collection-arguments.mjs +123 -0
  19. package/cli/collection-command-definitions.mjs +330 -0
  20. package/cli/collection-preflight.mjs +8 -1
  21. package/cli/command-argument-grammar.mjs +8 -210
  22. package/cli/command-definition.mjs +329 -0
  23. package/cli/command-reference.mjs +55 -1388
  24. package/cli/command-seeds.mjs +18 -0
  25. package/cli/compare.mjs +1 -1
  26. package/cli/config-profile.mjs +1 -1
  27. package/cli/ct-event-intake.mjs +4 -4
  28. package/cli/discover.mjs +2 -2
  29. package/cli/discovery-observation-snapshot.mjs +2 -2
  30. package/cli/discovery-scan-command-runner.mjs +3 -3
  31. package/cli/discovery-scan.mjs +1 -1
  32. package/cli/discovery-snapshot.mjs +2 -2
  33. package/cli/discovery-workflow.mjs +4 -4
  34. package/cli/domain-control-monitor.mjs +6 -6
  35. package/cli/domain-control-observations.mjs +2 -1
  36. package/cli/errors.mjs +5 -6
  37. package/cli/evidence-arguments.mjs +46 -0
  38. package/cli/evidence-command-definitions.mjs +69 -0
  39. package/cli/evidence-command-runner.mjs +2 -3
  40. package/cli/evidence-signing.mjs +3 -2
  41. package/cli/external-observation-mapping.mjs +2 -2
  42. package/cli/formatters/terminal-command-formats.mjs +6 -0
  43. package/cli/formatters/terminal-lookup.mjs +6 -0
  44. package/cli/history-arguments.mjs +39 -0
  45. package/cli/history-command-definitions.mjs +88 -0
  46. package/cli/indicator-set-command.mjs +33 -0
  47. package/cli/inline-command-families.mjs +6 -47
  48. package/cli/inline-command-runner.mjs +4 -31
  49. package/cli/input.mjs +2 -2
  50. package/cli/intake-command.mjs +107 -0
  51. package/cli/interchange-report.mjs +4 -2
  52. package/cli/investigation-artifacts.mjs +1 -1
  53. package/cli/investigation-plan.mjs +32 -154
  54. package/cli/investigation-recipes.mjs +177 -0
  55. package/cli/investigation-run.mjs +78 -12
  56. package/cli/local-mmdb-review.mjs +197 -17
  57. package/cli/lookalike-calibration.mjs +1 -1
  58. package/cli/lookup-brief.mjs +2 -2
  59. package/cli/lookup-command-runner.mjs +18 -35
  60. package/cli/lookup-diff.mjs +10 -9
  61. package/cli/lookup-plan.mjs +10 -14
  62. package/cli/lookup-reconcile.mjs +6 -5
  63. package/cli/lookup-timeline.mjs +7 -6
  64. package/cli/mail-header-review.mjs +24 -247
  65. package/cli/mail-review.mjs +9 -7
  66. package/cli/network-arguments.mjs +51 -0
  67. package/cli/network-command-definitions.mjs +130 -0
  68. package/cli/network-command-runner.mjs +43 -31
  69. package/cli/offline-evidence-review.mjs +39 -6
  70. package/cli/posture.mjs +1 -1
  71. package/cli/registry-fixture-scaffold.mjs +1 -1
  72. package/cli/retained-artifact-diff.mjs +8 -7
  73. package/cli/review-arguments.mjs +131 -0
  74. package/cli/review-command-definitions.mjs +273 -0
  75. package/cli/review-command-runner.mjs +68 -158
  76. package/cli/risk-calibration.mjs +8 -8
  77. package/cli/runner.mjs +20 -32
  78. package/cli/saved-lookup.mjs +2 -2
  79. package/cli/selected-input-worker.mjs +63 -0
  80. package/cli/sharing-review.mjs +5 -64
  81. package/cli/source-reliability.mjs +2 -2
  82. package/cli/support-arguments.mjs +49 -0
  83. package/cli/support-command-definitions.mjs +209 -0
  84. package/cli/support-command-runner.mjs +2 -2
  85. package/cli/workflow-arguments.mjs +86 -0
  86. package/cli/workflow-command-definitions.mjs +78 -0
  87. package/cli/workflow-command-runner.mjs +8 -1
  88. package/docs/cli-reference.md +27 -0
  89. package/docs/cli.md +223 -2
  90. package/docs/contextual-reviews.md +155 -0
  91. package/lib/analyst-taxonomy.mjs +2 -40
  92. package/lib/application-version.mjs +1 -1
  93. package/lib/availability.mjs +13 -789
  94. package/lib/bounded-contract-normalizers.mjs +4 -0
  95. package/lib/bounded-json.mjs +2 -330
  96. package/lib/browser-library-profile.mjs +62 -84
  97. package/lib/candidate-provenance-bounds.mjs +2 -0
  98. package/lib/classify.mjs +1 -1
  99. package/lib/ct-query.mjs +2 -27
  100. package/lib/ct-response-bounds.mjs +2 -9
  101. package/lib/ct-search.mjs +83 -47
  102. package/lib/dmarc-discovery.mjs +62 -0
  103. package/lib/dns-convergence-review.mjs +21 -8
  104. package/lib/dns-delegation-health.mjs +12 -8
  105. package/lib/dns-inheritance-review.mjs +53 -63
  106. package/lib/dns-intelligence.mjs +9 -7
  107. package/lib/dns-query-coverage.mjs +40 -0
  108. package/lib/domain-assurance.mjs +1 -1
  109. package/lib/domain-change-packet.mjs +12 -13
  110. package/lib/domain-change-review.mjs +32 -14
  111. package/lib/domain-control-flight-recorder.mjs +103 -27
  112. package/lib/domain-control-manifest.mjs +25 -17
  113. package/lib/domain-posture-analysis.mjs +22 -5
  114. package/lib/domain-posture.mjs +16 -15
  115. package/lib/domain-registration.mjs +392 -0
  116. package/lib/evidence-export-privacy.mjs +22 -15
  117. package/lib/evidence-export.mjs +3 -3
  118. package/lib/evidence-report.mjs +4 -1
  119. package/lib/external-intelligence-risk.mjs +2 -124
  120. package/lib/generated/cisa-kev-catalog.mjs +41 -3
  121. package/lib/generated/registrar-standing-catalogue.mjs +18 -10
  122. package/lib/generated/retire-browser-catalog.mjs +332 -19
  123. package/lib/generated/{unicode-confusables-17.mjs → unicode-confusables.mjs} +33 -33
  124. package/lib/html-signals.mjs +7 -2
  125. package/lib/http-evidence-bounds.mjs +2 -8
  126. package/lib/http-intelligence.mjs +13 -1
  127. package/lib/idn-confusable-policy.mjs +6 -4
  128. package/lib/idn-confusables.mjs +1 -1
  129. package/lib/interchange-fidelity-registry.mjs +10 -0
  130. package/lib/lookup-contract-primitives.mjs +1 -1
  131. package/lib/lookup-diagnostics.mjs +1 -23
  132. package/lib/lookup-network-evidence-bounds.mjs +1 -10
  133. package/lib/lookup-progress.mjs +50 -1
  134. package/lib/lookup-response-contract.mjs +69 -40
  135. package/lib/lookup-response.mjs +5 -15
  136. package/lib/lookup-source-progress.mjs +8 -22
  137. package/lib/lookup.mjs +1 -1
  138. package/lib/opportunity-scoring.mjs +2 -107
  139. package/lib/outbound-identity.mjs +1 -1
  140. package/lib/page-fingerprints.mjs +18 -1
  141. package/lib/perceptual-hash-comparison.mjs +2 -34
  142. package/lib/perceptual-hash.mjs +36 -10
  143. package/lib/portable-generator.mjs +2 -29
  144. package/lib/project-metadata.mjs +2 -8
  145. package/lib/rdap-client.mjs +11 -7
  146. package/lib/registrable-domain.mjs +2 -56
  147. package/lib/registrar-standing-contract.mjs +1 -1
  148. package/lib/registrar-standing.mjs +9 -13
  149. package/lib/registry-capabilities.mjs +2 -2
  150. package/lib/registry-capability-catalogue.mjs +27 -19
  151. package/lib/risk-calibration-summary.mjs +2 -352
  152. package/lib/risk-scoring.mjs +2 -345
  153. package/lib/scoring-evidence-quality.mjs +2 -107
  154. package/lib/semantic-version.mjs +2 -54
  155. package/lib/service-binding-dns.mjs +27 -0
  156. package/lib/smtp-transport-review.mjs +48 -19
  157. package/lib/sslbl-certificates.generated.mjs +141 -139
  158. package/lib/static-html-analysis.mjs +1 -1
  159. package/lib/structured-data-identity.mjs +1 -1
  160. package/lib/threat-intelligence-manifests.mjs +1 -1
  161. package/lib/threat-intelligence-runtime.mjs +1 -1
  162. package/lib/threat-intelligence-targets.mjs +1 -1
  163. package/lib/threat-intelligence-types.mjs +2 -75
  164. package/lib/typosquat-generator.mjs +11 -2
  165. package/lib/website-enrichment.mjs +388 -0
  166. package/lib/whois-authority.mjs +43 -5
  167. package/lib/whois-normalization.mjs +3 -1
  168. package/lib/whois-parser.mjs +5 -3
  169. package/package.json +13 -14
  170. package/packages/analysis/analyst-taxonomy.mjs +40 -0
  171. package/packages/analysis/bounded-json.mjs +330 -0
  172. package/packages/analysis/candidate-provenance-bounds.mjs +4 -0
  173. package/packages/analysis/cli-argument-grammar.mjs +216 -0
  174. package/packages/analysis/ct-query.mjs +27 -0
  175. package/packages/analysis/ct-response-bounds.mjs +9 -0
  176. package/packages/analysis/external-intelligence-risk.mjs +124 -0
  177. package/packages/analysis/http-evidence-bounds.mjs +8 -0
  178. package/packages/analysis/lookup-network-evidence-bounds.mjs +10 -0
  179. package/packages/analysis/opportunity-scoring.mjs +107 -0
  180. package/packages/analysis/perceptual-hash-comparison.mjs +34 -0
  181. package/packages/analysis/portable-generator.mjs +29 -0
  182. package/packages/analysis/project-metadata.mjs +8 -0
  183. package/packages/analysis/registrable-domain.mjs +56 -0
  184. package/packages/analysis/risk-calibration-summary.mjs +352 -0
  185. package/packages/analysis/risk-scoring.mjs +345 -0
  186. package/packages/analysis/scoring-evidence-quality.mjs +107 -0
  187. package/packages/analysis/semantic-version.mjs +54 -0
  188. package/packages/analysis/threat-intelligence-types.mjs +75 -0
  189. package/packages/cases/case-evidence-links.mjs +135 -0
  190. package/packages/cases/case-evidence-model.mjs +78 -12
  191. package/packages/cases/case-evidence-quality.mjs +5 -0
  192. package/packages/cases/case-export-input.mjs +7 -5
  193. package/packages/cases/case-incident-context.mjs +52 -0
  194. package/packages/cases/case-markdown.mjs +11 -0
  195. package/packages/cases/case-migration-model.mjs +40 -24
  196. package/packages/cases/case-recheck-model.mjs +90 -32
  197. package/packages/cases/case-record-contracts.mjs +1 -1
  198. package/packages/cases/case-record-core.mjs +1 -1
  199. package/packages/cases/case-record-operations.mjs +40 -112
  200. package/packages/cases/case-record-projection.mjs +8 -1
  201. package/packages/cases/case-record-version-input.mjs +19 -0
  202. package/packages/cases/case-report.mjs +63 -27
  203. package/packages/cases/case-requested-evidence.mjs +146 -0
  204. package/packages/cases/case-response-actions.mjs +103 -1
  205. package/packages/cases/case-response-model.mjs +9 -1
  206. package/packages/cases/case-response-outcomes.mjs +29 -8
  207. package/packages/cases/case-response-packet-render.mjs +13 -9
  208. package/packages/cases/case-response-packet.mjs +25 -11
  209. package/packages/cases/case-response-records.mjs +0 -1
  210. package/packages/cases/case-response-review-inputs.mjs +14 -3
  211. package/packages/cases/case-storage-model.mjs +1 -1
  212. package/packages/cases/case-workflow-metadata.mjs +225 -0
  213. package/packages/cases/case-workflow-migration.mjs +43 -0
  214. package/packages/cases/http-summary.mjs +6 -1
  215. package/packages/comparison/favicon-similarity.mjs +1 -1
  216. package/packages/comparison/page-similarity.mjs +1 -1
  217. package/packages/comparison/relationship-evidence.mjs +21 -9
  218. package/packages/comparison/relationship-provenance.mjs +7 -1
  219. package/packages/contracts/analyst-interchange.mjs +28 -10
  220. package/packages/contracts/case-portability.mjs +118 -25
  221. package/packages/contracts/cli-command-semantics.mjs +2 -0
  222. package/packages/contracts/cli-grammar.mjs +6 -0
  223. package/packages/contracts/cli-lookup-brief.mjs +2 -0
  224. package/packages/contracts/context-review.mjs +24 -0
  225. package/packages/contracts/document-intake.mjs +11 -0
  226. package/packages/contracts/domain-control-flight-recorder.mjs +30 -14
  227. package/packages/contracts/domain-control-manifest.mjs +1 -1
  228. package/packages/contracts/domain-control-monitor.mjs +13 -2
  229. package/packages/contracts/domain-control-review.mjs +36 -15
  230. package/packages/contracts/har-review.mjs +2 -0
  231. package/packages/contracts/identity-events.mjs +4 -0
  232. package/packages/contracts/investigation-run.mjs +2 -0
  233. package/packages/contracts/ip-address.mjs +10 -0
  234. package/packages/contracts/mail-authentication.mjs +5 -0
  235. package/packages/contracts/message-intake.mjs +31 -0
  236. package/packages/contracts/offline-comparison.mjs +4 -1
  237. package/packages/contracts/passive-mail.mjs +10 -0
  238. package/packages/contracts/web-capture.mjs +2 -2
  239. package/packages/contracts/workspace-portability.mjs +63 -17
  240. package/packages/evidence/collection-quality.mjs +67 -0
  241. package/packages/evidence/dns-query-outcome.mjs +72 -0
  242. package/packages/evidence/email-recipient.mjs +18 -0
  243. package/packages/evidence/lookup-target.mjs +5 -1
  244. package/packages/evidence/observation.mjs +2 -0
  245. package/packages/evidence/png-pixels.mjs +117 -0
  246. package/packages/evidence/public-address-policy.mjs +83 -0
  247. package/packages/interchange/defensive-indicator-export.mjs +264 -0
  248. package/packages/interchange/external-findings-import.mjs +4 -12
  249. package/packages/interchange/managed-indicator-export.mjs +35 -0
  250. package/packages/interchange/managed-indicator-set.mjs +210 -0
  251. package/packages/interchange/misp-indicator-export.mjs +93 -0
  252. package/packages/interchange/sharing-policy.mjs +56 -0
  253. package/packages/interchange/stix-indicator-export.mjs +129 -0
  254. package/packages/interchange/web-capture-import.mjs +22 -15
  255. package/packages/investigation/acquisition-decision-packet.mjs +1 -1
  256. package/packages/investigation/bulk-mail-exposure.mjs +7 -13
  257. package/packages/investigation/capture-coverage.mjs +57 -0
  258. package/packages/investigation/connector-provenance-review.mjs +100 -0
  259. package/packages/investigation/context-review.mjs +35 -0
  260. package/packages/investigation/document-intake.mjs +81 -0
  261. package/packages/investigation/docx-intake.mjs +133 -0
  262. package/packages/investigation/domain-history-review.mjs +100 -0
  263. package/packages/investigation/domain-transition-review.mjs +47 -0
  264. package/packages/investigation/evidence-coverage-ledger.mjs +9 -1
  265. package/packages/investigation/har-intake.mjs +68 -0
  266. package/packages/investigation/identity-event-intake.mjs +131 -0
  267. package/packages/investigation/identity-incident-review.mjs +39 -0
  268. package/packages/investigation/incident-sequence-review.mjs +58 -0
  269. package/packages/investigation/intake-report.mjs +19 -0
  270. package/packages/investigation/investigation-manifest.mjs +2 -2
  271. package/packages/investigation/link-intake.mjs +179 -0
  272. package/packages/investigation/lookup-asset-graph.mjs +1 -1
  273. package/packages/investigation/mail-authentication-review.mjs +222 -0
  274. package/packages/investigation/mail-header-identity.mjs +209 -0
  275. package/packages/investigation/message-intake.mjs +195 -0
  276. package/packages/investigation/page-behaviour.mjs +113 -0
  277. package/packages/investigation/pdf-intake.mjs +155 -0
  278. package/packages/investigation/platform-continuity-review.mjs +60 -0
  279. package/packages/investigation/qr-intake.mjs +56 -0
  280. package/packages/investigation/requested-action-hints.mjs +11 -0
  281. package/packages/investigation/selected-input-review.mjs +17 -0
  282. package/packages/investigation/storefront-review.mjs +70 -0
  283. package/packages/workspace/brand-profile-model.mjs +2 -2
  284. package/packages/workspace/bulk-review-model.mjs +28 -26
  285. package/packages/workspace/bulk-session-model.mjs +23 -13
  286. package/packages/workspace/campaign-model.mjs +1 -1
  287. package/packages/workspace/detection-rule-model.mjs +1 -1
  288. package/packages/workspace/hostile-input.mjs +1 -1
  289. package/packages/workspace/investigation-guide.mjs +2 -2
  290. package/packages/workspace/investigation-template-model.mjs +26 -2
  291. package/packages/workspace/page-baseline.mjs +2 -2
  292. package/packages/workspace/relationship-observation-model.mjs +17 -13
  293. package/packages/workspace/shortlist-model.mjs +14 -5
  294. package/packages/workspace/watchlist-history.mjs +28 -12
  295. package/packages/workspace/watchlist-store.mjs +17 -5
  296. package/packages/workspace/website-snapshot-model.mjs +28 -3
  297. package/packages/workspace/workspace-archive-crypto.mjs +1 -1
  298. package/packages/workspace/workspace-archive.mjs +5 -4
  299. package/third-party-notices.txt +549 -16
  300. package/lib/hostname.mjs +0 -2
@@ -205,12 +205,17 @@ class SocketReplyReader {
205
205
  #endedError = null;
206
206
  bytesRead = 0;
207
207
  lineCount = 0;
208
+ #onData = (chunk) => this.#receive(chunk);
209
+ #onError = (error) => this.#fail(error);
210
+ #onEnd = () => this.#fail(new Error('SMTP server closed the connection before completing a reply.'));
211
+ #onTimeout = () => this.#fail(new Error('SMTP transport timed out.'));
208
212
  constructor(socket) {
209
213
  this.#socket = socket;
210
- socket.on('data', (chunk) => this.#receive(Buffer.from(chunk)));
211
- socket.once('error', (error) => this.#fail(error));
212
- socket.once('end', () => this.#fail(new Error('SMTP server closed the connection before completing a reply.')));
213
- socket.once('timeout', () => this.#fail(new Error('SMTP transport timed out.')));
214
+ socket.on('data', this.#onData);
215
+ socket.once('error', this.#onError);
216
+ socket.once('end', this.#onEnd);
217
+ socket.once('close', this.#onEnd);
218
+ socket.once('timeout', this.#onTimeout);
214
219
  }
215
220
  #receive(chunk) {
216
221
  if (this.#endedError)
@@ -281,10 +286,14 @@ class SocketReplyReader {
281
286
  }
282
287
  release() {
283
288
  this.assertIdle();
284
- this.#socket.removeAllListeners('data');
285
- this.#socket.removeAllListeners('error');
286
- this.#socket.removeAllListeners('end');
287
- this.#socket.removeAllListeners('timeout');
289
+ this.detach();
290
+ }
291
+ detach() {
292
+ this.#socket.removeListener('data', this.#onData);
293
+ this.#socket.removeListener('error', this.#onError);
294
+ this.#socket.removeListener('end', this.#onEnd);
295
+ this.#socket.removeListener('close', this.#onEnd);
296
+ this.#socket.removeListener('timeout', this.#onTimeout);
288
297
  }
289
298
  }
290
299
  function smtpStartTlsOptions(socket, hostname) {
@@ -297,10 +306,18 @@ function smtpStartTlsOptions(socket, hostname) {
297
306
  checkServerIdentity: () => undefined,
298
307
  };
299
308
  }
300
- async function defaultSmtpProbe(options) {
301
- const socket = net.createConnection({ host: options.address, port: SMTP_PORT, family: options.family });
309
+ async function defaultSmtpProbe(options, transport = {
310
+ connect: options => net.createConnection(options),
311
+ startTls: options => tls.connect(options),
312
+ }) {
313
+ options.signal.throwIfAborted();
314
+ const socket = transport.connect({ host: options.address, port: SMTP_PORT, family: options.family });
315
+ let activeSocket = socket;
316
+ let reader = null;
302
317
  socket.setTimeout(options.timeoutMs);
303
- const aborted = () => socket.destroy(new Error('SMTP endpoint review timed out.'));
318
+ // Closing the active phase rejects its pending read/handshake. Do not emit
319
+ // an unhandled error on the raw socket after ownership has moved to TLS.
320
+ const aborted = () => { activeSocket.destroy(); };
304
321
  options.signal.addEventListener('abort', aborted, { once: true });
305
322
  try {
306
323
  await new Promise((resolve, reject) => {
@@ -308,38 +325,48 @@ async function defaultSmtpProbe(options) {
308
325
  socket.removeListener('connect', connected);
309
326
  socket.removeListener('error', failed);
310
327
  socket.removeListener('timeout', timedOut);
328
+ socket.removeListener('close', closed);
311
329
  };
312
330
  const connected = () => { cleanup(); resolve(); };
313
331
  const failed = (error) => { cleanup(); socket.destroy(); reject(error); };
314
332
  const timedOut = () => { cleanup(); socket.destroy(); reject(new Error('SMTP connection timed out.')); };
333
+ const closed = () => failed(new Error('SMTP connection closed before connecting.'));
315
334
  socket.once('connect', connected);
316
335
  socket.once('error', failed);
317
336
  socket.once('timeout', timedOut);
337
+ socket.once('close', closed);
318
338
  if (options.signal.aborted)
319
339
  aborted();
320
340
  });
321
- const reader = new SocketReplyReader(socket);
341
+ const replyReader = new SocketReplyReader(socket);
342
+ reader = replyReader;
322
343
  const connection = {
323
344
  remoteAddress: socket.remoteAddress || null,
324
- readReply: () => reader.readReply(),
325
- assertIdle: () => reader.assertIdle(),
345
+ readReply: () => replyReader.readReply(),
346
+ assertIdle: () => replyReader.assertIdle(),
326
347
  write: (command) => new Promise((resolve, reject) => socket.write(command, (error) => error ? reject(error) : resolve())),
327
348
  startTls: async (hostname) => {
328
- reader.release();
329
- const tlsSocket = tls.connect(smtpStartTlsOptions(socket, hostname));
349
+ replyReader.release();
350
+ const tlsSocket = transport.startTls(smtpStartTlsOptions(socket, hostname));
351
+ activeSocket = tlsSocket;
330
352
  tlsSocket.setTimeout(options.timeoutMs);
331
353
  await new Promise((resolve, reject) => {
332
354
  const cleanup = () => {
333
355
  tlsSocket.removeListener('secureConnect', secured);
334
356
  tlsSocket.removeListener('error', failed);
335
357
  tlsSocket.removeListener('timeout', timedOut);
358
+ tlsSocket.removeListener('close', closed);
336
359
  };
337
360
  const secured = () => { cleanup(); resolve(); };
338
361
  const failed = (error) => { cleanup(); tlsSocket.destroy(); reject(error); };
339
362
  const timedOut = () => { cleanup(); tlsSocket.destroy(); reject(new Error('SMTP STARTTLS handshake timed out.')); };
363
+ const closed = () => failed(new Error('SMTP STARTTLS connection closed before completing the handshake.'));
340
364
  tlsSocket.once('secureConnect', secured);
341
365
  tlsSocket.once('error', failed);
342
366
  tlsSocket.once('timeout', timedOut);
367
+ tlsSocket.once('close', closed);
368
+ if (options.signal.aborted)
369
+ aborted();
343
370
  });
344
371
  const cipher = tlsSocket.getCipher();
345
372
  return Object.freeze({
@@ -351,13 +378,15 @@ async function defaultSmtpProbe(options) {
351
378
  remoteAddress: tlsSocket.remoteAddress || null,
352
379
  });
353
380
  },
354
- diagnostics: () => ({ bytesRead: reader.bytesRead, lineCount: reader.lineCount }),
355
- destroy: () => socket.destroy(),
381
+ diagnostics: () => ({ bytesRead: replyReader.bytesRead, lineCount: replyReader.lineCount }),
382
+ destroy: () => { activeSocket.destroy(); socket.destroy(); },
356
383
  };
357
384
  return await runSmtpConversation(options.hostname, connection);
358
385
  }
359
386
  finally {
360
387
  options.signal.removeEventListener('abort', aborted);
388
+ reader?.detach();
389
+ activeSocket.destroy();
361
390
  socket.destroy();
362
391
  }
363
392
  }
@@ -796,4 +825,4 @@ function formatMailTransportReview(review) {
796
825
  lines.push(` - ${limitation}`);
797
826
  return `${lines.join('\n')}\n`;
798
827
  }
799
- export { EHLO_COMMAND, MAIL_TRANSPORT_INPUT_SCHEMA, MAIL_TRANSPORT_INPUT_VERSION, MAIL_TRANSPORT_REVIEW_SCHEMA, MAIL_TRANSPORT_REVIEW_VERSION, MAIL_TRANSPORT_TOTAL_TIMEOUT_MS, MAX_MAIL_TRANSPORT_CONCURRENCY, MAX_MAIL_TRANSPORT_ADDRESS_CANDIDATES, MAX_MAIL_TRANSPORT_DNS_ALIASES, MAX_MAIL_TRANSPORT_INPUT_BYTES, MAX_MAIL_TRANSPORT_TARGETS, MAX_SMTP_CAPABILITIES, MAX_SMTP_LINE_BYTES, MAX_SMTP_REPLY_LINES, MAX_SMTP_RESPONSE_BYTES, SMTP_ENDPOINT_TIMEOUT_MS, STARTTLS_COMMAND, collectMailTransportReview, certificateObservation, formatMailTransportReview, normalizeSmtpReply, parseMailTransportInput, resolveSelectedHost, runSmtpConversation, smtpStartTlsOptions, smtpCapabilities, };
828
+ export { EHLO_COMMAND, MAIL_TRANSPORT_INPUT_SCHEMA, MAIL_TRANSPORT_INPUT_VERSION, MAIL_TRANSPORT_REVIEW_SCHEMA, MAIL_TRANSPORT_REVIEW_VERSION, MAIL_TRANSPORT_TOTAL_TIMEOUT_MS, MAX_MAIL_TRANSPORT_CONCURRENCY, MAX_MAIL_TRANSPORT_ADDRESS_CANDIDATES, MAX_MAIL_TRANSPORT_DNS_ALIASES, MAX_MAIL_TRANSPORT_INPUT_BYTES, MAX_MAIL_TRANSPORT_TARGETS, MAX_SMTP_CAPABILITIES, MAX_SMTP_LINE_BYTES, MAX_SMTP_REPLY_LINES, MAX_SMTP_RESPONSE_BYTES, SMTP_ENDPOINT_TIMEOUT_MS, STARTTLS_COMMAND, collectMailTransportReview, certificateObservation, formatMailTransportReview, normalizeSmtpReply, parseMailTransportInput, resolveSelectedHost, runSmtpConversation, smtpStartTlsOptions, smtpCapabilities, SocketReplyReader, defaultSmtpProbe, };