@slicedearth/whoisleuth-cli 2.3.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 (418) hide show
  1. package/NOTICE +8 -2
  2. package/README.md +19 -15
  3. package/bin/whoisleuth.mjs +8 -1
  4. package/cli/archive-content-digest.mjs +14 -0
  5. package/cli/archive-inspect.mjs +20 -53
  6. package/cli/argument-values.mjs +55 -0
  7. package/cli/arguments.mjs +24 -408
  8. package/cli/artifact-validation/case-response.mjs +65 -44
  9. package/cli/artifact-validation/investigation-capsule.mjs +52 -31
  10. package/cli/artifact-validation/lookup-evidence.mjs +15 -9
  11. package/cli/artifact-validation/signed-review.mjs +136 -68
  12. package/cli/artifact-validation/structure-primitives.mjs +1 -105
  13. package/cli/artifact-verify.mjs +92 -24
  14. package/cli/assurance-arguments.mjs +56 -0
  15. package/cli/assurance-command-definitions.mjs +179 -0
  16. package/cli/assurance-command-runner.mjs +40 -5
  17. package/cli/bagit-folder.mjs +57 -0
  18. package/cli/bagit-review.mjs +23 -0
  19. package/cli/bounded-json.mjs +1 -1
  20. package/cli/bulk-checkpoint.mjs +1 -1
  21. package/cli/bulk-command-runner.mjs +4 -2
  22. package/cli/bulk-output.mjs +29 -3
  23. package/cli/bulk.mjs +2 -3
  24. package/cli/case-command.mjs +212 -0
  25. package/cli/case-pack.mjs +50 -32
  26. package/cli/ci-report.mjs +6 -3
  27. package/cli/collection-arguments.mjs +123 -0
  28. package/cli/collection-command-definitions.mjs +330 -0
  29. package/cli/collection-preflight.mjs +8 -1
  30. package/cli/command-argument-grammar.mjs +8 -206
  31. package/cli/command-definition.mjs +329 -0
  32. package/cli/command-reference.mjs +94 -1357
  33. package/cli/command-seeds.mjs +18 -0
  34. package/cli/compare.mjs +1 -1
  35. package/cli/completion.mjs +298 -79
  36. package/cli/config-profile.mjs +8 -6
  37. package/cli/ct-event-intake.mjs +16 -16
  38. package/cli/discover.mjs +5 -4
  39. package/cli/discovery-observation-snapshot.mjs +46 -18
  40. package/cli/discovery-scan-command-runner.mjs +5 -3
  41. package/cli/discovery-scan.mjs +7 -4
  42. package/cli/discovery-snapshot.mjs +2 -2
  43. package/cli/discovery-workflow.mjs +5 -5
  44. package/cli/domain-control-monitor.mjs +50 -20
  45. package/cli/domain-control-observations.mjs +151 -103
  46. package/cli/errors.mjs +37 -6
  47. package/cli/evidence-arguments.mjs +46 -0
  48. package/cli/evidence-command-definitions.mjs +69 -0
  49. package/cli/evidence-command-runner.mjs +18 -8
  50. package/cli/evidence-signing.mjs +5 -4
  51. package/cli/external-observation-mapping.mjs +9 -10
  52. package/cli/formatters/terminal-command-formats.mjs +6 -0
  53. package/cli/formatters/terminal-lookup.mjs +24 -46
  54. package/cli/formatters/terminal-shared.mjs +5 -3
  55. package/cli/formatters/terminal-technology.mjs +114 -0
  56. package/cli/history-arguments.mjs +39 -0
  57. package/cli/history-command-definitions.mjs +88 -0
  58. package/cli/indicator-set-command.mjs +33 -0
  59. package/cli/inline-command-families.mjs +6 -46
  60. package/cli/inline-command-runner.mjs +4 -31
  61. package/cli/input.mjs +2 -2
  62. package/cli/intake-command.mjs +107 -0
  63. package/cli/interactive-launcher.mjs +2 -160
  64. package/cli/interchange-report.mjs +8 -10
  65. package/cli/investigation-artifacts.mjs +176 -0
  66. package/cli/investigation-checkpoint.mjs +10 -0
  67. package/cli/investigation-folder.mjs +114 -0
  68. package/cli/investigation-manifest.mjs +1 -112
  69. package/cli/investigation-package-review.mjs +103 -0
  70. package/cli/investigation-plan.mjs +38 -147
  71. package/cli/investigation-recipes.mjs +177 -0
  72. package/cli/investigation-run.mjs +256 -35
  73. package/cli/local-document-checkpoint.mjs +170 -0
  74. package/cli/local-mmdb-review.mjs +197 -17
  75. package/cli/lookalike-calibration.mjs +1 -1
  76. package/cli/lookup-brief.mjs +2 -2
  77. package/cli/lookup-browser.mjs +5 -12
  78. package/cli/lookup-command-runner.mjs +33 -39
  79. package/cli/lookup-diff.mjs +47 -12
  80. package/cli/lookup-plan.mjs +16 -14
  81. package/cli/lookup-reconcile.mjs +15 -12
  82. package/cli/lookup-timeline.mjs +7 -6
  83. package/cli/mail-header-review.mjs +24 -247
  84. package/cli/mail-review.mjs +75 -21
  85. package/cli/manual.mjs +1 -0
  86. package/cli/network-arguments.mjs +51 -0
  87. package/cli/network-command-definitions.mjs +130 -0
  88. package/cli/network-command-runner.mjs +45 -31
  89. package/cli/offline-evidence-review.mjs +39 -6
  90. package/cli/output-file.mjs +31 -5
  91. package/cli/posture.mjs +1 -1
  92. package/cli/registry-doctor.mjs +3 -1
  93. package/cli/registry-fixture-scaffold.mjs +1 -1
  94. package/cli/registry-support.mjs +1 -1
  95. package/cli/retained-artifact-diff.mjs +10 -9
  96. package/cli/review-arguments.mjs +131 -0
  97. package/cli/review-command-definitions.mjs +273 -0
  98. package/cli/review-command-runner.mjs +104 -149
  99. package/cli/risk-calibration.mjs +8 -8
  100. package/cli/runner.mjs +74 -37
  101. package/cli/saved-lookup.mjs +2 -2
  102. package/cli/selected-input-worker.mjs +63 -0
  103. package/cli/sharing-review.mjs +8 -80
  104. package/cli/signer-trust.mjs +104 -0
  105. package/cli/source-reliability.mjs +75 -84
  106. package/cli/support-arguments.mjs +49 -0
  107. package/cli/support-command-definitions.mjs +209 -0
  108. package/cli/support-command-runner.mjs +2 -2
  109. package/cli/terminal-input.mjs +168 -0
  110. package/cli/workflow-arguments.mjs +86 -0
  111. package/cli/workflow-command-definitions.mjs +78 -0
  112. package/cli/workflow-command-runner.mjs +75 -13
  113. package/docs/cli-reference.md +103 -30
  114. package/docs/cli.md +510 -25
  115. package/docs/contextual-reviews.md +155 -0
  116. package/lib/abort.mjs +4 -1
  117. package/lib/analyst-taxonomy.mjs +2 -40
  118. package/lib/application-version.mjs +1 -1
  119. package/lib/availability.mjs +27 -754
  120. package/lib/bounded-contract-normalizers.mjs +4 -0
  121. package/lib/bounded-file.mjs +3 -1
  122. package/lib/bounded-html-document.mjs +125 -0
  123. package/lib/bounded-json.mjs +2 -290
  124. package/lib/browser-library-profile.mjs +99 -130
  125. package/lib/browser-library-worker.mjs +112 -0
  126. package/lib/candidate-provenance-bounds.mjs +2 -0
  127. package/lib/classify.mjs +1 -1
  128. package/lib/client-behavior-profile.mjs +3 -3
  129. package/lib/ct-query.mjs +2 -27
  130. package/lib/ct-response-bounds.mjs +2 -9
  131. package/lib/ct-search.mjs +89 -46
  132. package/lib/dmarc-discovery.mjs +62 -0
  133. package/lib/dns-convergence-review.mjs +21 -8
  134. package/lib/dns-delegation-health.mjs +36 -22
  135. package/lib/dns-inheritance-review.mjs +207 -0
  136. package/lib/dns-intelligence.mjs +44 -29
  137. package/lib/dns-mx.mjs +1 -1
  138. package/lib/dns-query-coverage.mjs +40 -0
  139. package/lib/dnssec-evidence-validation.mjs +11 -3
  140. package/lib/domain-assurance.mjs +1 -1
  141. package/lib/domain-change-packet.mjs +18 -14
  142. package/lib/domain-change-review.mjs +40 -16
  143. package/lib/domain-control-flight-recorder.mjs +301 -124
  144. package/lib/domain-control-manifest.mjs +126 -58
  145. package/lib/domain-posture-analysis.mjs +41 -11
  146. package/lib/domain-posture-parsers.mjs +88 -6
  147. package/lib/domain-posture.mjs +120 -32
  148. package/lib/domain-registration.mjs +392 -0
  149. package/lib/evidence-export-privacy.mjs +568 -0
  150. package/lib/evidence-export.mjs +12 -593
  151. package/lib/evidence-report.mjs +7 -2
  152. package/lib/external-intelligence-risk.mjs +2 -124
  153. package/lib/favicon.mjs +117 -41
  154. package/lib/generated/cisa-kev-catalog.mjs +50 -4
  155. package/lib/generated/registrar-standing-catalogue.mjs +18 -10
  156. package/lib/generated/retire-browser-catalog.mjs +2742 -1034
  157. package/lib/generated/{unicode-confusables-17.mjs → unicode-confusables.mjs} +33 -33
  158. package/lib/html-signals.mjs +87 -85
  159. package/lib/http-evidence-bounds.mjs +2 -7
  160. package/lib/http-intelligence.mjs +52 -27
  161. package/lib/idn-confusable-policy.mjs +6 -4
  162. package/lib/idn-confusables.mjs +1 -1
  163. package/lib/interchange-fidelity-registry.mjs +10 -0
  164. package/lib/lookup-cache.mjs +34 -11
  165. package/lib/lookup-child-profile-contract.mjs +24 -15
  166. package/lib/lookup-contract-primitives.mjs +1 -1
  167. package/lib/lookup-diagnostics.mjs +2 -1
  168. package/lib/lookup-network-evidence-bounds.mjs +1 -10
  169. package/lib/lookup-progress.mjs +79 -13
  170. package/lib/lookup-response-contract.mjs +1077 -0
  171. package/lib/lookup-response.mjs +11 -24
  172. package/lib/lookup-source-progress.mjs +24 -35
  173. package/lib/lookup.mjs +49 -28
  174. package/lib/observed-network-context.mjs +43 -27
  175. package/lib/opportunity-scoring.mjs +2 -107
  176. package/lib/outbound-identity.mjs +1 -1
  177. package/lib/outbound-request-bounds.mjs +4 -1
  178. package/lib/page-fingerprints.mjs +87 -134
  179. package/lib/page-role-profile.mjs +12 -8
  180. package/lib/perceptual-hash-comparison.mjs +2 -34
  181. package/lib/perceptual-hash.mjs +79 -24
  182. package/lib/portable-generator.mjs +2 -29
  183. package/lib/project-metadata.mjs +2 -8
  184. package/lib/rdap-bootstrap.mjs +72 -22
  185. package/lib/rdap-client.mjs +26 -14
  186. package/lib/rdap-normalization.mjs +33 -18
  187. package/lib/rdap-search-workbench.mjs +1 -1
  188. package/lib/rdap-transport.mjs +47 -20
  189. package/lib/rdap-types.mjs +2 -1
  190. package/lib/rdap.mjs +18 -3
  191. package/lib/registrable-domain.mjs +2 -36
  192. package/lib/registrar-standing-contract.mjs +2 -1
  193. package/lib/registrar-standing.mjs +9 -13
  194. package/lib/registry-capabilities.mjs +7 -3
  195. package/lib/registry-capability-catalogue.mjs +29 -20
  196. package/lib/registry-dates.mjs +2 -190
  197. package/lib/registry-insights.mjs +56 -18
  198. package/lib/response-policy.mjs +86 -48
  199. package/lib/risk-calibration-summary.mjs +2 -338
  200. package/lib/risk-scoring.mjs +2 -345
  201. package/lib/rpki-evidence.mjs +8 -5
  202. package/lib/safe-fetch.mjs +54 -47
  203. package/lib/scoring-evidence-quality.mjs +2 -107
  204. package/lib/security-txt.mjs +10 -7
  205. package/lib/semantic-version.mjs +2 -54
  206. package/lib/service-binding-dns.mjs +35 -0
  207. package/lib/smtp-transport-review.mjs +75 -34
  208. package/lib/sslbl-certificates.generated.mjs +141 -138
  209. package/lib/static-html-analysis.mjs +117 -146
  210. package/lib/structured-data-identity.mjs +2 -1
  211. package/lib/technology-markup.mjs +100 -0
  212. package/lib/threat-intelligence-manifests.mjs +11 -139
  213. package/lib/threat-intelligence-runtime.mjs +24 -52
  214. package/lib/threat-intelligence-targets.mjs +6 -34
  215. package/lib/threat-intelligence-types.mjs +2 -36
  216. package/lib/typosquat-generator.mjs +29 -16
  217. package/lib/urlhaus-intelligence.mjs +8 -3
  218. package/lib/urlscan-intelligence.mjs +1 -1
  219. package/lib/website-enrichment.mjs +388 -0
  220. package/lib/website-security-posture.mjs +30 -6
  221. package/lib/website-technology.mjs +111 -71
  222. package/lib/whois-authority.mjs +55 -5
  223. package/lib/whois-chain.mjs +9 -2
  224. package/lib/whois-common-formats.mjs +5 -5
  225. package/lib/whois-contracts.mjs +2 -1
  226. package/lib/whois-dialects.mjs +2 -2
  227. package/lib/whois-normalization.mjs +3 -1
  228. package/lib/whois-parser-support.mjs +8 -1
  229. package/lib/whois-parser.mjs +5 -3
  230. package/lib/whois-transport.mjs +23 -7
  231. package/package.json +14 -14
  232. package/packages/analysis/analyst-taxonomy.mjs +40 -0
  233. package/packages/analysis/bounded-json.mjs +330 -0
  234. package/packages/analysis/candidate-provenance-bounds.mjs +4 -0
  235. package/packages/analysis/cli-argument-grammar.mjs +216 -0
  236. package/packages/analysis/ct-query.mjs +27 -0
  237. package/packages/analysis/ct-response-bounds.mjs +9 -0
  238. package/packages/analysis/external-intelligence-risk.mjs +124 -0
  239. package/packages/analysis/http-evidence-bounds.mjs +8 -0
  240. package/packages/analysis/lookup-network-evidence-bounds.mjs +10 -0
  241. package/packages/analysis/opportunity-scoring.mjs +107 -0
  242. package/packages/analysis/perceptual-hash-comparison.mjs +34 -0
  243. package/packages/analysis/portable-generator.mjs +29 -0
  244. package/packages/analysis/project-metadata.mjs +8 -0
  245. package/packages/analysis/registrable-domain.mjs +56 -0
  246. package/packages/analysis/risk-calibration-summary.mjs +352 -0
  247. package/packages/analysis/risk-scoring.mjs +345 -0
  248. package/packages/analysis/scoring-evidence-quality.mjs +107 -0
  249. package/packages/analysis/semantic-version.mjs +54 -0
  250. package/packages/analysis/threat-intelligence-types.mjs +75 -0
  251. package/packages/cases/case-attachment-model.mjs +83 -0
  252. package/packages/cases/case-evidence-links.mjs +135 -0
  253. package/packages/cases/case-evidence-model.mjs +229 -69
  254. package/packages/cases/case-evidence-quality.mjs +5 -0
  255. package/packages/cases/case-export-input.mjs +55 -0
  256. package/packages/cases/case-incident-context.mjs +52 -0
  257. package/packages/cases/case-markdown.mjs +11 -0
  258. package/packages/cases/case-migration-model.mjs +98 -48
  259. package/packages/cases/case-model.mjs +1 -0
  260. package/packages/cases/case-recheck-model.mjs +149 -0
  261. package/packages/cases/case-record-contracts.mjs +1 -1
  262. package/packages/cases/case-record-core.mjs +4 -3
  263. package/packages/cases/case-record-operations.mjs +123 -133
  264. package/packages/cases/case-record-projection.mjs +30 -20
  265. package/packages/cases/case-record-version-input.mjs +19 -0
  266. package/packages/cases/case-report.mjs +114 -67
  267. package/packages/cases/case-requested-evidence.mjs +146 -0
  268. package/packages/cases/case-response-actions.mjs +756 -0
  269. package/packages/cases/case-response-model.mjs +49 -1129
  270. package/packages/cases/case-response-outcomes.mjs +338 -0
  271. package/packages/cases/case-response-packet-render.mjs +157 -0
  272. package/packages/cases/case-response-packet-types.mjs +1 -0
  273. package/packages/cases/case-response-packet-vocabulary.mjs +48 -0
  274. package/packages/cases/case-response-packet.mjs +58 -593
  275. package/packages/cases/case-response-records.mjs +93 -0
  276. package/packages/cases/case-response-review-inputs.mjs +382 -0
  277. package/packages/cases/case-response-values.mjs +85 -0
  278. package/packages/cases/case-review-package.mjs +45 -0
  279. package/packages/cases/case-selection.mjs +46 -0
  280. package/packages/cases/case-storage-model.mjs +26 -1
  281. package/packages/cases/case-workflow-metadata.mjs +225 -0
  282. package/packages/cases/case-workflow-migration.mjs +43 -0
  283. package/packages/cases/http-summary.mjs +6 -1
  284. package/packages/cases/response-route-freshness.mjs +16 -0
  285. package/packages/comparison/capture-context.mjs +61 -0
  286. package/packages/comparison/comparison-ledger-bulk.mjs +4 -1
  287. package/packages/comparison/favicon-similarity.mjs +1 -1
  288. package/packages/comparison/page-similarity.mjs +3 -2
  289. package/packages/comparison/relationship-evidence.mjs +103 -14
  290. package/packages/comparison/relationship-provenance.mjs +99 -0
  291. package/packages/contracts/analyst-interchange.mjs +234 -0
  292. package/packages/contracts/analyst-review-state-contract.mjs +11 -0
  293. package/packages/contracts/analyst-review-state.mjs +5 -4
  294. package/packages/contracts/case-portability.mjs +370 -114
  295. package/packages/contracts/case-views-contract.mjs +12 -0
  296. package/packages/contracts/case-views.mjs +26 -0
  297. package/packages/contracts/cli-command-semantics.mjs +3 -0
  298. package/packages/contracts/cli-grammar.mjs +6 -0
  299. package/packages/contracts/cli-lookup-brief.mjs +2 -0
  300. package/packages/contracts/cli-lookup.mjs +0 -1
  301. package/packages/contracts/context-review.mjs +24 -0
  302. package/packages/contracts/document-intake.mjs +11 -0
  303. package/packages/contracts/domain-control-flight-recorder.mjs +98 -44
  304. package/packages/contracts/domain-control-manifest.mjs +128 -74
  305. package/packages/contracts/domain-control-monitor.mjs +59 -45
  306. package/packages/contracts/domain-control-review.mjs +200 -121
  307. package/packages/contracts/domain-name.mjs +21 -0
  308. package/packages/contracts/external-observation-interchange.mjs +2 -1
  309. package/packages/contracts/extracted-domain-lifecycle.mjs +11 -32
  310. package/packages/contracts/har-review.mjs +2 -0
  311. package/packages/contracts/http-url.mjs +2 -0
  312. package/packages/contracts/identity-events.mjs +4 -0
  313. package/packages/contracts/investigation-package-limits.mjs +24 -0
  314. package/packages/contracts/investigation-portability.mjs +56 -27
  315. package/packages/contracts/investigation-run.mjs +18 -0
  316. package/packages/contracts/ip-address.mjs +44 -0
  317. package/packages/contracts/lookup-evidence.mjs +35 -0
  318. package/packages/contracts/mail-authentication.mjs +5 -0
  319. package/packages/contracts/message-intake.mjs +31 -0
  320. package/packages/contracts/offline-comparison.mjs +4 -2
  321. package/packages/contracts/page-fingerprints.mjs +15 -0
  322. package/packages/contracts/passive-mail.mjs +10 -0
  323. package/packages/contracts/risk-calibration.mjs +0 -1
  324. package/packages/contracts/schema-compatibility.mjs +1 -1
  325. package/packages/contracts/schema-lifecycle.mjs +83 -153
  326. package/packages/contracts/selected-file-limits.mjs +6 -0
  327. package/packages/contracts/vulnerability-identifiers.mjs +5 -0
  328. package/packages/contracts/web-capture.mjs +10 -0
  329. package/packages/contracts/workspace-portability.mjs +219 -238
  330. package/packages/evidence/artifact-integrity.mjs +8 -2
  331. package/packages/evidence/artifact-structure.mjs +105 -0
  332. package/packages/evidence/collection-quality.mjs +67 -0
  333. package/packages/evidence/decision-fact.mjs +4 -1
  334. package/packages/evidence/dns-query-outcome.mjs +72 -0
  335. package/packages/evidence/domain-control-runtime.mjs +155 -27
  336. package/packages/evidence/domain-posture-context.mjs +79 -0
  337. package/packages/evidence/email-recipient.mjs +18 -0
  338. package/packages/evidence/image-regions.mjs +56 -0
  339. package/packages/evidence/latest-observations.mjs +28 -0
  340. package/packages/evidence/lookup-target.mjs +108 -0
  341. package/packages/evidence/observation.mjs +18 -1
  342. package/packages/evidence/passphrase-encryption.mjs +44 -0
  343. package/packages/evidence/png-pixels.mjs +117 -0
  344. package/packages/evidence/public-address-policy.mjs +83 -0
  345. package/packages/evidence/record-identity.mjs +72 -0
  346. package/packages/evidence/registry-dates.mjs +190 -0
  347. package/packages/evidence/retained-file.mjs +69 -0
  348. package/packages/evidence/review-age.mjs +14 -0
  349. package/packages/interchange/bagit.mjs +342 -0
  350. package/packages/interchange/bounded-zip-extraction.mjs +278 -0
  351. package/packages/interchange/crc32.mjs +17 -0
  352. package/packages/interchange/defensive-indicator-export.mjs +264 -0
  353. package/packages/interchange/external-findings-import.mjs +93 -61
  354. package/packages/interchange/managed-indicator-export.mjs +35 -0
  355. package/packages/interchange/managed-indicator-set.mjs +210 -0
  356. package/packages/interchange/misp-indicator-export.mjs +93 -0
  357. package/packages/interchange/sharing-policy.mjs +56 -0
  358. package/packages/interchange/stix-indicator-export.mjs +129 -0
  359. package/packages/interchange/web-capture-import.mjs +389 -0
  360. package/packages/investigation/acquisition-decision-packet.mjs +1 -1
  361. package/packages/investigation/bulk-mail-exposure.mjs +9 -14
  362. package/packages/investigation/capture-coverage.mjs +57 -0
  363. package/packages/investigation/connector-provenance-review.mjs +100 -0
  364. package/packages/investigation/context-review.mjs +35 -0
  365. package/packages/investigation/document-intake.mjs +81 -0
  366. package/packages/investigation/docx-intake.mjs +133 -0
  367. package/packages/investigation/domain-history-review.mjs +100 -0
  368. package/packages/investigation/domain-transition-review.mjs +47 -0
  369. package/packages/investigation/evidence-coverage-ledger.mjs +9 -1
  370. package/packages/investigation/har-intake.mjs +68 -0
  371. package/packages/investigation/identity-event-intake.mjs +131 -0
  372. package/packages/investigation/identity-incident-review.mjs +39 -0
  373. package/packages/investigation/incident-sequence-review.mjs +58 -0
  374. package/packages/investigation/intake-report.mjs +19 -0
  375. package/packages/investigation/investigation-bagit.mjs +14 -0
  376. package/packages/investigation/investigation-capsule.mjs +33 -5
  377. package/packages/investigation/investigation-manifest.mjs +200 -0
  378. package/packages/investigation/investigation-package-crypto.mjs +98 -0
  379. package/packages/investigation/investigation-package.mjs +200 -0
  380. package/packages/investigation/link-intake.mjs +179 -0
  381. package/packages/investigation/lookup-asset-graph-inputs.mjs +38 -0
  382. package/packages/investigation/lookup-asset-graph.mjs +161 -141
  383. package/packages/investigation/lookup-claim-readiness.mjs +18 -0
  384. package/packages/investigation/lookup-investigation-brief.mjs +3 -3
  385. package/packages/investigation/lookup-task-guidance.mjs +58 -0
  386. package/packages/investigation/mail-authentication-review.mjs +222 -0
  387. package/packages/investigation/mail-header-identity.mjs +209 -0
  388. package/packages/investigation/message-intake.mjs +195 -0
  389. package/packages/investigation/page-behaviour.mjs +113 -0
  390. package/packages/investigation/pdf-intake.mjs +155 -0
  391. package/packages/investigation/platform-continuity-review.mjs +60 -0
  392. package/packages/investigation/qr-intake.mjs +56 -0
  393. package/packages/investigation/requested-action-hints.mjs +11 -0
  394. package/packages/investigation/selected-input-review.mjs +17 -0
  395. package/packages/investigation/storefront-review.mjs +70 -0
  396. package/packages/monitoring/analyst-review-state.mjs +38 -90
  397. package/packages/workspace/brand-profile-model.mjs +160 -22
  398. package/packages/workspace/bulk-columns.mjs +17 -0
  399. package/packages/workspace/bulk-review-model.mjs +39 -31
  400. package/packages/workspace/bulk-session-model.mjs +112 -27
  401. package/packages/workspace/bulk-sort.mjs +1 -0
  402. package/packages/workspace/campaign-model.mjs +1 -1
  403. package/packages/workspace/case-views.mjs +102 -0
  404. package/packages/workspace/detection-rule-model.mjs +1 -1
  405. package/packages/workspace/hostile-input.mjs +29 -8
  406. package/packages/workspace/investigation-guide.mjs +2 -2
  407. package/packages/workspace/investigation-template-model.mjs +45 -6
  408. package/packages/workspace/page-baseline.mjs +20 -17
  409. package/packages/workspace/relationship-observation-model.mjs +54 -35
  410. package/packages/workspace/shortlist-model.mjs +14 -5
  411. package/packages/workspace/watchlist-history.mjs +30 -14
  412. package/packages/workspace/watchlist-store.mjs +24 -6
  413. package/packages/workspace/website-snapshot-model.mjs +98 -33
  414. package/packages/workspace/workspace-archive-crypto.mjs +41 -61
  415. package/packages/workspace/workspace-archive.mjs +90 -25
  416. package/third-party-notices.txt +577 -17
  417. package/lib/hostname.mjs +0 -38
  418. package/packages/investigation/bulk-review-export.mjs +0 -63
@@ -1,124 +1,2 @@
1
- // Converts already-returned, separately attributed external observations into
2
- // a conservative Risk contribution. Unknown providers and lone publisher
3
- // families never contribute. Two adapters operated by the same publisher are
4
- // deliberately one corroboration source, even when their datasets differ.
5
- export const EXTERNAL_INTELLIGENCE_CALIBRATION_VERSION = 1;
6
- export const EXTERNAL_INTELLIGENCE_RECENT_DAYS = 90;
7
- const DAY_MS = 24 * 60 * 60 * 1000;
8
- const MAX_CLOCK_SKEW_MS = DAY_MS;
9
- const MAX_PROVIDERS = 10;
10
- const MAX_FINDINGS_PER_PROVIDER = 100;
11
- const POSITIVE_STATES = new Set(['success', 'partial']);
12
- const QUALIFYING_CATEGORIES = new Set(['phishing', 'malware']);
13
- // Only built-in provider IDs can affect the built-in score. The two community
14
- // malware datasets share one publisher family and therefore cannot corroborate
15
- // one another by themselves.
16
- import { normalizeExplicitIsoTimestamp } from "../packages/evidence/observation.mjs";
17
- import { canonicalRegistrableDomain } from "./registrable-domain.mjs";
18
- import { THREAT_INTELLIGENCE_CONTRACT_VERSION, THREAT_INTELLIGENCE_ENVELOPE_VERSION, THREAT_INTELLIGENCE_SCHEMA, } from "./threat-intelligence-types.mjs";
19
- const PUBLISHER_FAMILIES = Object.freeze({
20
- urlscan_search: 'archived-scan-publisher',
21
- urlhaus_host: 'community-malware-publisher',
22
- threatfox_domain_ioc: 'community-malware-publisher',
23
- });
24
- function record(value) {
25
- return value && typeof value === 'object' && !Array.isArray(value) ? value : null;
26
- }
27
- function timestamp(value) {
28
- const normalized = normalizeExplicitIsoTimestamp(value);
29
- return normalized ? Date.parse(normalized) : null;
30
- }
31
- function providerEvidence(value, expectedDomain) {
32
- const provider = record(value);
33
- const identity = record(provider?.provider);
34
- const observation = record(provider?.observation);
35
- const target = record(provider?.target);
36
- const providerId = typeof identity?.id === 'string' ? identity.id : '';
37
- const publisherFamily = Object.hasOwn(PUBLISHER_FAMILIES, providerId)
38
- ? PUBLISHER_FAMILIES[providerId]
39
- : null;
40
- if (provider?.schema !== THREAT_INTELLIGENCE_SCHEMA
41
- || provider.version !== THREAT_INTELLIGENCE_CONTRACT_VERSION
42
- || target?.type !== 'domain'
43
- || target.exposure !== 'registrable_domain'
44
- || target.value !== expectedDomain
45
- || !publisherFamily
46
- || typeof provider?.state !== 'string'
47
- || !POSITIVE_STATES.has(provider.state)
48
- || !Array.isArray(provider.findings))
49
- return null;
50
- const observedAt = timestamp(observation?.observedAt);
51
- let latestFindingAt = null;
52
- let qualifyingFindings = 0;
53
- for (const item of provider.findings.slice(0, MAX_FINDINGS_PER_PROVIDER)) {
54
- const finding = record(item);
55
- if (!finding || typeof finding.category !== 'string' || !QUALIFYING_CATEGORIES.has(finding.category))
56
- continue;
57
- const firstObservedAt = timestamp(finding.firstObservedAt);
58
- const lastObservedAt = timestamp(finding.lastObservedAt);
59
- if (firstObservedAt !== null && lastObservedAt !== null && firstObservedAt > lastObservedAt)
60
- continue;
61
- qualifyingFindings += 1;
62
- const candidate = lastObservedAt ?? firstObservedAt;
63
- if (candidate !== null && (latestFindingAt === null || candidate > latestFindingAt))
64
- latestFindingAt = candidate;
65
- }
66
- if (!qualifyingFindings)
67
- return null;
68
- let ageDays = null;
69
- if (observedAt !== null && latestFindingAt !== null && latestFindingAt <= observedAt + MAX_CLOCK_SKEW_MS) {
70
- ageDays = Math.max(0, Math.floor((observedAt - latestFindingAt) / DAY_MS));
71
- }
72
- return {
73
- providerId,
74
- publisherFamily,
75
- qualifyingFindings,
76
- lastObservedAt: latestFindingAt === null ? null : new Date(latestFindingAt).toISOString(),
77
- ageDays,
78
- recent: ageDays !== null && ageDays <= EXTERNAL_INTELLIGENCE_RECENT_DAYS,
79
- };
80
- }
81
- export function calibrateExternalIntelligenceRisk(value, expectedDomainValue) {
82
- const envelope = record(value);
83
- const expectedDomain = canonicalRegistrableDomain(expectedDomainValue);
84
- const providers = expectedDomain
85
- && envelope?.version === THREAT_INTELLIGENCE_ENVELOPE_VERSION
86
- && Array.isArray(envelope.providers)
87
- ? envelope.providers.slice(0, MAX_PROVIDERS)
88
- : [];
89
- const byProvider = new Map();
90
- for (const item of providers) {
91
- const evidence = providerEvidence(item, expectedDomain ?? '');
92
- if (!evidence || byProvider.has(evidence.providerId))
93
- continue;
94
- byProvider.set(evidence.providerId, evidence);
95
- }
96
- const sources = [...byProvider.values()].sort((a, b) => a.providerId.localeCompare(b.providerId));
97
- const publisherFamilies = new Set(sources.map((source) => source.publisherFamily));
98
- const recentPublisherFamilies = new Set(sources.filter((source) => source.recent).map((source) => source.publisherFamily));
99
- const knownAges = sources.map((source) => source.ageDays).filter((age) => age !== null);
100
- const independentPublisherCount = publisherFamilies.size;
101
- const recentPublisherCount = recentPublisherFamilies.size;
102
- let contribution = 0;
103
- let factor = null;
104
- if (independentPublisherCount >= 2) {
105
- contribution = recentPublisherCount >= 2 ? 18 : 10;
106
- factor = {
107
- label: recentPublisherCount >= 2
108
- ? 'Corroborated recent external phishing/malware records'
109
- : 'Corroborated external phishing/malware records',
110
- delta: contribution,
111
- };
112
- }
113
- return {
114
- version: EXTERNAL_INTELLIGENCE_CALIBRATION_VERSION,
115
- contribution,
116
- factor,
117
- eligibleProviderCount: sources.length,
118
- independentPublisherCount,
119
- recentPublisherCount,
120
- freshestAgeDays: knownAges.length ? Math.min(...knownAges) : null,
121
- unknownAgeProviderCount: sources.filter((source) => source.ageDays === null).length,
122
- sources,
123
- };
124
- }
1
+ // Retained public import; the runtime-neutral implementation lives in the domain layer.
2
+ export * from "../packages/analysis/external-intelligence-risk.mjs";
package/lib/favicon.mjs CHANGED
@@ -1,50 +1,30 @@
1
- // Favicon-hash fetch - a lookalike/typosquat domain that serves the same
2
- // favicon as a brand's real site is a strong sign of a cloned phishing kit
3
- // (attackers copy the favicon along with the rest of the page); a domain
4
- // that merely resolves and serves *some* page proves much less.
5
- //
6
- // Two hashes are produced from the same bytes:
7
- // - hash: exact SHA-256 of the raw bytes. Zero false positives, but only
8
- // catches a byte-for-byte copy.
9
- // - phash: perceptual (fuzzy) dHash (lib/perceptual-hash.mts). Catches a
10
- // resized/recompressed/re-saved copy that's visually identical but
11
- // no longer byte-identical - the common case when the favicon
12
- // passed through a different tool than the original. Null when the
13
- // image format can't be decoded (GIF/JPEG/SVG), so it strictly
14
- // adds coverage without weakening the exact tier.
1
+ // Bounded favicon acquisition. Recognised image bytes produce an exact SHA-256;
2
+ // supported decoded pixels can also produce a heuristic dHash. Neither match
3
+ // establishes ownership, shared infrastructure or maliciousness. HTML error
4
+ // bodies are not image evidence and must not end candidate fallback.
15
5
  import * as crypto from 'node:crypto';
16
6
  import { safeFetch, readBytesCapped } from "./safe-fetch.mjs";
17
7
  import { whoisleuthRequestHeaders } from "./outbound-identity.mjs";
18
8
  import { faviconPerceptualHash } from "./perceptual-hash.mjs";
9
+ import { analyzeStaticHtml } from "./static-html-analysis.mjs";
10
+ import { isHtmlElement, parseBoundedHtml } from "./bounded-html-document.mjs";
19
11
  import { FAVICON_FETCH_TIMEOUT_MS, MAX_FAVICON_BYTES, MAX_FAVICON_CANDIDATES, } from "./outbound-request-bounds.mjs";
20
12
  // Extracts favicon URLs declared in the page's own <link rel="...icon..."> tags
21
13
  // (resolved to absolute URLs against the page origin), in preference order:
22
- // standard "icon"/"shortcut icon" first, then "apple-touch-icon". Many modern
23
- // sites (e.g. npm) serve no /favicon.ico at all and only declare a PNG on a
24
- // CDN this way, so checking only /favicon.ico misses them entirely. data:
14
+ // standard "icon"/"shortcut icon" first, then "apple-touch-icon". data:
25
15
  // URIs are passed through verbatim - decodeFaviconCandidate handles them
26
16
  // without a network fetch.
27
- function extractIconUrls(html, baseUrl) {
28
- const links = [];
29
- for (const tag of html.match(/<link\b[^>]*>/gi) || []) {
30
- const rel = (tag.match(/\brel\s*=\s*["']([^"']*)["']/i) || [])[1];
31
- if (!rel || !/icon/i.test(rel))
32
- continue;
33
- const href = (tag.match(/\bhref\s*=\s*["']([^"']+)["']/i) || [])[1];
34
- if (!href)
35
- continue;
36
- links.push({ href: href.trim(), priority: /apple-touch/i.test(rel) ? 1 : 0 });
37
- }
38
- links.sort((a, b) => a.priority - b.priority);
17
+ function extractIconUrls(html, baseUrl, suppliedAnalysis) {
18
+ const analysis = suppliedAnalysis ?? analyzeStaticHtml(html, { baseUrl });
39
19
  const urls = [];
40
- for (const { href } of links) {
20
+ for (const { href } of analysis.iconLinks) {
41
21
  if (/^data:/i.test(href)) {
42
22
  urls.push(href);
43
23
  continue;
44
24
  }
45
25
  try {
46
- const resolved = new URL(href, baseUrl);
47
- if (resolved.protocol === 'http:' || resolved.protocol === 'https:')
26
+ const resolved = new URL(href, analysis.effectiveBaseUrl ?? baseUrl);
27
+ if (['http:', 'https:'].includes(resolved.protocol) && !resolved.username && !resolved.password)
48
28
  urls.push(resolved.toString());
49
29
  }
50
30
  catch {
@@ -56,21 +36,114 @@ function extractIconUrls(html, baseUrl) {
56
36
  // Decodes an inline `data:` favicon (base64 or percent-encoded) into a byte
57
37
  // buffer, bounded to MAX_FAVICON_BYTES. Returns null on anything malformed.
58
38
  function decodeDataUri(uri) {
39
+ // Percent encoding is at most three input characters per output byte.
40
+ // Refuse oversized encoded input before slicing or decoding it.
41
+ if (uri.length > MAX_FAVICON_BYTES * 3 + 128)
42
+ return null;
59
43
  const comma = uri.indexOf(',');
60
- if (comma === -1)
44
+ if (comma === -1 || comma > 128)
61
45
  return null;
62
46
  const meta = uri.slice(5, comma);
63
47
  const data = uri.slice(comma + 1);
64
48
  try {
65
- const bytes = /;base64/i.test(meta)
49
+ const base64 = /;base64$/i.test(meta);
50
+ if (base64 && (data.length > Math.ceil(MAX_FAVICON_BYTES / 3) * 4
51
+ || !/^[A-Za-z0-9+/]*={0,2}$/u.test(data)))
52
+ return null;
53
+ const bytes = base64
66
54
  ? Buffer.from(data, 'base64')
67
- : Buffer.from(decodeURIComponent(data), 'latin1');
55
+ : Buffer.from(decodeURIComponent(data), 'utf8');
68
56
  return bytes.length > 0 && bytes.length <= MAX_FAVICON_BYTES ? bytes : null;
69
57
  }
70
58
  catch {
71
59
  return null;
72
60
  }
73
61
  }
62
+ // Admission recognises container framing, not every codec feature or rendered
63
+ // meaning. Exact-only formats remain usable; fuzzy decoding has its own pixel
64
+ // and inflate limits. All loops here operate within MAX_FAVICON_BYTES.
65
+ function isFaviconImage(bytes) {
66
+ if (bytes.length < 6 || bytes.length > MAX_FAVICON_BYTES)
67
+ return false;
68
+ if (bytes.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) {
69
+ let dataSeen = false;
70
+ for (let offset = 8; offset + 12 <= bytes.length;) {
71
+ const size = bytes.readUInt32BE(offset);
72
+ const end = offset + 12 + size;
73
+ if (end > bytes.length)
74
+ return false;
75
+ const type = bytes.toString('ascii', offset + 4, offset + 8);
76
+ if (offset === 8 && (type !== 'IHDR' || size !== 13
77
+ || bytes.readUInt32BE(offset + 8) === 0 || bytes.readUInt32BE(offset + 12) === 0))
78
+ return false;
79
+ if (type === 'IDAT' && size > 0)
80
+ dataSeen = true;
81
+ if (type === 'IEND')
82
+ return size === 0 && dataSeen && end === bytes.length;
83
+ offset = end;
84
+ }
85
+ return false;
86
+ }
87
+ if (bytes.readUInt32LE(0) === 0x00010000) {
88
+ const count = bytes.readUInt16LE(4);
89
+ const directoryEnd = 6 + count * 16;
90
+ if (!count || directoryEnd > bytes.length)
91
+ return false;
92
+ for (let index = 0; index < count; index += 1) {
93
+ const entry = 6 + index * 16;
94
+ const size = bytes.readUInt32LE(entry + 8);
95
+ const offset = bytes.readUInt32LE(entry + 12);
96
+ if (size < 12 || offset < directoryEnd || offset + size > bytes.length)
97
+ continue;
98
+ const payload = bytes.subarray(offset, offset + size);
99
+ if (payload.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))
100
+ || [12, 40, 52, 56, 108, 124].includes(payload.readUInt32LE(0)))
101
+ return true;
102
+ }
103
+ return false;
104
+ }
105
+ if (/^GIF8[79]a$/u.test(bytes.toString('ascii', 0, 6))) {
106
+ return bytes.length >= 14 && bytes.readUInt16LE(6) > 0 && bytes.readUInt16LE(8) > 0 && bytes.at(-1) === 0x3b;
107
+ }
108
+ if (bytes.length >= 12 && bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff) {
109
+ return bytes.at(-2) === 0xff && bytes.at(-1) === 0xd9;
110
+ }
111
+ if (bytes.length >= 20 && bytes.toString('ascii', 0, 4) === 'RIFF'
112
+ && bytes.toString('ascii', 8, 12) === 'WEBP') {
113
+ return bytes.readUInt32LE(4) + 8 === bytes.length && ['VP8 ', 'VP8L', 'VP8X'].includes(bytes.toString('ascii', 12, 16));
114
+ }
115
+ // Standalone SVG needs an SVG root, not an SVG embedded in an HTML error
116
+ // page. Native tree construction discards neither an HTML wrapper nor sibling
117
+ // content here. No script, entity, resource or stylesheet is executed.
118
+ const source = bytes.toString('utf8');
119
+ if (!source.includes('<svg'))
120
+ return false;
121
+ const parsed = parseBoundedHtml(source);
122
+ if (parsed.inputLimitReached || parsed.constructionLimitReached)
123
+ return false;
124
+ const html = parsed.document.childNodes.find(isHtmlElement);
125
+ if (html?.sourceCodeLocation?.startTag || parsed.document.childNodes.some((node) => node.nodeName === '#documentType' && 'name' in node && node.name !== 'svg'))
126
+ return false;
127
+ const head = html?.childNodes.find((node) => isHtmlElement(node) && node.tagName === 'head');
128
+ if (head && isHtmlElement(head) && (head.sourceCodeLocation?.startTag
129
+ || head.childNodes.some((node) => node.nodeName !== '#comment'
130
+ && !(node.nodeName === '#text' && 'value' in node && !node.value.trim()))))
131
+ return false;
132
+ const body = html?.childNodes.find((node) => isHtmlElement(node) && node.tagName === 'body');
133
+ if (!body || !isHtmlElement(body) || body.sourceCodeLocation?.startTag)
134
+ return false;
135
+ const content = body.childNodes.filter((node) => node.nodeName !== '#comment'
136
+ && !(node.nodeName === '#text' && 'value' in node && !node.value.trim()));
137
+ const root = content[0];
138
+ if (content.length !== 1 || !root || !('tagName' in root) || root.tagName !== 'svg'
139
+ || root.namespaceURI !== 'http://www.w3.org/2000/svg'
140
+ || !root.attrs.some((attribute) => attribute.name === 'xmlns' && attribute.value === 'http://www.w3.org/2000/svg'))
141
+ return false;
142
+ const location = root.sourceCodeLocation;
143
+ if (!location?.startTag)
144
+ return false;
145
+ return Boolean(location.endTag || /\/\s*>$/u.test(source.slice(location.startTag.startOffset, location.startTag.endOffset)));
146
+ }
74
147
  // Returns the favicon bytes for one candidate URL (a real fetch, or an inline
75
148
  // data: decode), or null if it can't be retrieved/used.
76
149
  async function fetchFaviconBytes(url, headers, fetcher, timeoutMs) {
@@ -107,15 +180,15 @@ async function fetchFaviconBytes(url, headers, fetcher, timeoutMs) {
107
180
  // provided (the deep-check path already has the homepage in hand), is scanned
108
181
  // for declared <link rel="icon"> URLs, which are tried before the bare
109
182
  // /favicon.ico fallback.
110
- function buildFaviconCandidates(domain, html = '') {
183
+ function buildFaviconCandidates(domain, html = '', options = {}) {
111
184
  const candidates = [];
112
185
  const seen = new Set();
113
186
  const add = (url) => { if (url && !seen.has(url)) {
114
187
  seen.add(url);
115
188
  candidates.push(url);
116
189
  } };
117
- if (html)
118
- for (const url of extractIconUrls(html, `https://${domain}/`))
190
+ if (html || options.htmlAnalysis)
191
+ for (const url of extractIconUrls(html, options.baseUrl ?? `https://${domain}/`, options.htmlAnalysis))
119
192
  add(url);
120
193
  add(`https://${domain}/favicon.ico`);
121
194
  add(`https://${domain}/favicon.svg`);
@@ -123,16 +196,19 @@ function buildFaviconCandidates(domain, html = '') {
123
196
  add(`http://${domain}/favicon.svg`);
124
197
  return candidates.slice(0, MAX_FAVICON_CANDIDATES);
125
198
  }
126
- async function fetchFaviconHash(domain, { html = '', fetcher = safeFetch, timeoutMs = FAVICON_FETCH_TIMEOUT_MS } = {}) {
199
+ async function fetchFaviconHash(domain, { html = '', baseUrl, htmlAnalysis, fetcher = safeFetch, timeoutMs = FAVICON_FETCH_TIMEOUT_MS } = {}) {
127
200
  const headers = whoisleuthRequestHeaders();
128
- const candidates = buildFaviconCandidates(domain, html);
201
+ const candidates = buildFaviconCandidates(domain, html, {
202
+ ...(baseUrl !== undefined ? { baseUrl } : {}),
203
+ ...(htmlAnalysis ? { htmlAnalysis } : {}),
204
+ });
129
205
  const requestTimeoutMs = Number.isInteger(timeoutMs) && timeoutMs >= 10 && timeoutMs <= FAVICON_FETCH_TIMEOUT_MS
130
206
  ? timeoutMs
131
207
  : FAVICON_FETCH_TIMEOUT_MS;
132
208
  for (const url of candidates) {
133
209
  // eslint-disable-next-line no-await-in-loop
134
210
  const bytes = await fetchFaviconBytes(url, headers, fetcher, requestTimeoutMs);
135
- if (bytes) {
211
+ if (bytes && isFaviconImage(bytes)) {
136
212
  return {
137
213
  hash: crypto.createHash('sha256').update(bytes).digest('hex'),
138
214
  phash: faviconPerceptualHash(bytes),
@@ -1,9 +1,9 @@
1
1
  // Generated by tools/cisa-kev-catalog.mts from the pinned CISA KEV feed.
2
2
  // United States Government work; do not edit by hand.
3
3
  const CISA_KEV_CATALOG = Object.freeze({
4
- catalogVersion: "2026.08.31",
5
- releasedAt: "2026-08-31T14:55:13.3856Z",
6
- sourceSha256: "2043ec4073019154e781f687359bfd9759e4d1ca9a18befc99fbe0c4c93bbde8",
4
+ catalogVersion: "2026.10.02",
5
+ releasedAt: "2026-10-02T15:19:38.2945Z",
6
+ sourceSha256: "d2c8c6cb23291b46ff2b086197641a6b1fa35e6b746bba714cc280a1778f9e48",
7
7
  sourceUrl: "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json",
8
8
  identifiers: Object.freeze([
9
9
  "CVE-2002-0367",
@@ -1439,6 +1439,7 @@ const CISA_KEV_CATALOG = Object.freeze({
1439
1439
  "CVE-2025-24991",
1440
1440
  "CVE-2025-24993",
1441
1441
  "CVE-2025-25181",
1442
+ "CVE-2025-25249",
1442
1443
  "CVE-2025-25257",
1443
1444
  "CVE-2025-26399",
1444
1445
  "CVE-2025-26633",
@@ -1484,6 +1485,8 @@ const CISA_KEV_CATALOG = Object.freeze({
1484
1485
  "CVE-2025-38352",
1485
1486
  "CVE-2025-3928",
1486
1487
  "CVE-2025-3935",
1488
+ "CVE-2025-39682",
1489
+ "CVE-2025-39964",
1487
1490
  "CVE-2025-4008",
1488
1491
  "CVE-2025-40536",
1489
1492
  "CVE-2025-40551",
@@ -1571,6 +1574,9 @@ const CISA_KEV_CATALOG = Object.freeze({
1571
1574
  "CVE-2026-0257",
1572
1575
  "CVE-2026-0300",
1573
1576
  "CVE-2026-0770",
1577
+ "CVE-2026-102489",
1578
+ "CVE-2026-102490",
1579
+ "CVE-2026-104286",
1574
1580
  "CVE-2026-10520",
1575
1581
  "CVE-2026-11645",
1576
1582
  "CVE-2026-12569",
@@ -1584,7 +1590,9 @@ const CISA_KEV_CATALOG = Object.freeze({
1584
1590
  "CVE-2026-1731",
1585
1591
  "CVE-2026-18556",
1586
1592
  "CVE-2026-18577",
1593
+ "CVE-2026-19490",
1587
1594
  "CVE-2026-20045",
1595
+ "CVE-2026-20079",
1588
1596
  "CVE-2026-20122",
1589
1597
  "CVE-2026-20127",
1590
1598
  "CVE-2026-20128",
@@ -1644,6 +1652,8 @@ const CISA_KEV_CATALOG = Object.freeze({
1644
1652
  "CVE-2026-39987",
1645
1653
  "CVE-2026-41091",
1646
1654
  "CVE-2026-41940",
1655
+ "CVE-2026-42016",
1656
+ "CVE-2026-42018",
1647
1657
  "CVE-2026-42208",
1648
1658
  "CVE-2026-42271",
1649
1659
  "CVE-2026-42897",
@@ -1656,13 +1666,17 @@ const CISA_KEV_CATALOG = Object.freeze({
1656
1666
  "CVE-2026-48172",
1657
1667
  "CVE-2026-48282",
1658
1668
  "CVE-2026-48558",
1669
+ "CVE-2026-48710",
1659
1670
  "CVE-2026-48907",
1660
1671
  "CVE-2026-48908",
1661
1672
  "CVE-2026-48939",
1673
+ "CVE-2026-49869",
1662
1674
  "CVE-2026-50522",
1663
1675
  "CVE-2026-50751",
1664
1676
  "CVE-2026-5281",
1677
+ "CVE-2026-53266",
1665
1678
  "CVE-2026-53362",
1679
+ "CVE-2026-5430",
1666
1680
  "CVE-2026-54420",
1667
1681
  "CVE-2026-55040",
1668
1682
  "CVE-2026-55255",
@@ -1671,28 +1685,60 @@ const CISA_KEV_CATALOG = Object.freeze({
1671
1685
  "CVE-2026-56290",
1672
1686
  "CVE-2026-56291",
1673
1687
  "CVE-2026-58644",
1688
+ "CVE-2026-58704",
1674
1689
  "CVE-2026-59310",
1690
+ "CVE-2026-59822",
1675
1691
  "CVE-2026-60004",
1676
1692
  "CVE-2026-60137",
1677
1693
  "CVE-2026-63030",
1678
1694
  "CVE-2026-63077",
1679
1695
  "CVE-2026-64849",
1680
1696
  "CVE-2026-65400",
1697
+ "CVE-2026-65660",
1681
1698
  "CVE-2026-66384",
1699
+ "CVE-2026-67277",
1700
+ "CVE-2026-67279",
1682
1701
  "CVE-2026-68820",
1683
1702
  "CVE-2026-6973",
1703
+ "CVE-2026-71362",
1684
1704
  "CVE-2026-72529",
1685
1705
  "CVE-2026-72530",
1706
+ "CVE-2026-7273",
1686
1707
  "CVE-2026-72898",
1687
1708
  "CVE-2026-73570",
1688
1709
  "CVE-2026-7473",
1710
+ "CVE-2026-75650",
1711
+ "CVE-2026-76460",
1712
+ "CVE-2026-76461",
1713
+ "CVE-2026-76504",
1689
1714
  "CVE-2026-8037",
1690
1715
  "CVE-2026-81578",
1716
+ "CVE-2026-81963",
1691
1717
  "CVE-2026-82078",
1718
+ "CVE-2026-82329",
1719
+ "CVE-2026-83548",
1720
+ "CVE-2026-83549",
1692
1721
  "CVE-2026-8398",
1693
1722
  "CVE-2026-8452",
1723
+ "CVE-2026-84869",
1724
+ "CVE-2026-85046",
1725
+ "CVE-2026-85102",
1726
+ "CVE-2026-85706",
1727
+ "CVE-2026-85880",
1728
+ "CVE-2026-86060",
1729
+ "CVE-2026-86218",
1730
+ "CVE-2026-86950",
1731
+ "CVE-2026-87491",
1732
+ "CVE-2026-87886",
1733
+ "CVE-2026-87902",
1734
+ "CVE-2026-88771",
1735
+ "CVE-2026-88772",
1694
1736
  "CVE-2026-9082",
1695
- "CVE-2026-9198"
1737
+ "CVE-2026-9198",
1738
+ "CVE-2026-93616",
1739
+ "CVE-2026-93952",
1740
+ "CVE-2026-94127",
1741
+ "CVE-2026-9586"
1696
1742
  ]),
1697
1743
  });
1698
1744
  export { CISA_KEV_CATALOG };