@cyvest/cyvest-js 5.4.0 → 6.0.0

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.
package/dist/index.cjs CHANGED
@@ -36,30 +36,30 @@ __export(index_exports, {
36
36
  areConnected: () => areConnected,
37
37
  compareLevels: () => compareLevels,
38
38
  countRelationshipsByType: () => countRelationshipsByType,
39
- findCheckByName: () => findCheckByName,
40
- findChecksAtLeast: () => findChecksAtLeast,
41
- findChecksByLevel: () => findChecksByLevel,
42
- findChecksForObservable: () => findChecksForObservable,
43
- findChecksForTag: () => findChecksForTag,
44
39
  findExternalObservables: () => findExternalObservables,
45
- findHighestScoringChecks: () => findHighestScoringChecks,
40
+ findFindingByName: () => findFindingByName,
41
+ findFindingsAtLeast: () => findFindingsAtLeast,
42
+ findFindingsByLevel: () => findFindingsByLevel,
43
+ findFindingsForObservable: () => findFindingsForObservable,
44
+ findFindingsForTag: () => findFindingsForTag,
45
+ findHighestScoringFindings: () => findHighestScoringFindings,
46
46
  findHighestScoringObservables: () => findHighestScoringObservables,
47
47
  findInternalObservables: () => findInternalObservables,
48
48
  findLeafObservables: () => findLeafObservables,
49
- findMaliciousChecks: () => findMaliciousChecks,
49
+ findMaliciousFindings: () => findMaliciousFindings,
50
50
  findMaliciousObservables: () => findMaliciousObservables,
51
51
  findObservablesAtLeast: () => findObservablesAtLeast,
52
52
  findObservablesByLevel: () => findObservablesByLevel,
53
53
  findObservablesByType: () => findObservablesByType,
54
54
  findObservablesByValue: () => findObservablesByValue,
55
55
  findObservablesContaining: () => findObservablesContaining,
56
- findObservablesForCheck: () => findObservablesForCheck,
56
+ findObservablesForFinding: () => findObservablesForFinding,
57
57
  findObservablesMatching: () => findObservablesMatching,
58
58
  findObservablesWithThreatIntel: () => findObservablesWithThreatIntel,
59
59
  findOrphanObservables: () => findOrphanObservables,
60
60
  findPath: () => findPath,
61
61
  findSourceObservables: () => findSourceObservables,
62
- findSuspiciousChecks: () => findSuspiciousChecks,
62
+ findSuspiciousFindings: () => findSuspiciousFindings,
63
63
  findSuspiciousObservables: () => findSuspiciousObservables,
64
64
  findTagsAtLeast: () => findTagsAtLeast,
65
65
  findTagsByLevel: () => findTagsByLevel,
@@ -69,22 +69,21 @@ __export(index_exports, {
69
69
  findThreatIntelBySource: () => findThreatIntelBySource,
70
70
  findThreatIntelsForObservable: () => findThreatIntelsForObservable,
71
71
  findWhitelistedObservables: () => findWhitelistedObservables,
72
- generateCheckKey: () => generateCheckKey,
73
72
  generateEnrichmentKey: () => generateEnrichmentKey,
73
+ generateFindingKey: () => generateFindingKey,
74
74
  generateObservableKey: () => generateObservableKey,
75
75
  generateTagKey: () => generateTagKey,
76
76
  generateThreatIntelKey: () => generateThreatIntelKey,
77
- getAllCheckKeys: () => getAllCheckKeys,
78
- getAllChecks: () => getAllChecks,
79
77
  getAllEnrichments: () => getAllEnrichments,
78
+ getAllEvidences: () => getAllEvidences,
79
+ getAllFindingKeys: () => getAllFindingKeys,
80
+ getAllFindings: () => getAllFindings,
80
81
  getAllObservableTypes: () => getAllObservableTypes,
81
82
  getAllObservables: () => getAllObservables,
82
83
  getAllRelationshipTypes: () => getAllRelationshipTypes,
83
84
  getAllTags: () => getAllTags,
84
85
  getAllThreatIntelSources: () => getAllThreatIntelSources,
85
86
  getAllThreatIntels: () => getAllThreatIntels,
86
- getCheck: () => getCheck,
87
- getCheckByName: () => getCheckByName,
88
87
  getColorForLevel: () => getColorForLevel,
89
88
  getColorForScore: () => getColorForScore,
90
89
  getCounts: () => getCounts,
@@ -92,6 +91,9 @@ __export(index_exports, {
92
91
  getEnrichment: () => getEnrichment,
93
92
  getEnrichmentByName: () => getEnrichmentByName,
94
93
  getEntityLevel: () => getEntityLevel,
94
+ getEvidence: () => getEvidence,
95
+ getFinding: () => getFinding,
96
+ getFindingByName: () => getFindingByName,
95
97
  getLevelFromScore: () => getLevelFromScore,
96
98
  getObservable: () => getObservable,
97
99
  getObservableByTypeValue: () => getObservableByTypeValue,
@@ -127,13 +129,13 @@ __export(index_exports, {
127
129
  maxLevel: () => maxLevel,
128
130
  minLevel: () => minLevel,
129
131
  normalizeLevel: () => normalizeLevel,
130
- parseCheckKey: () => parseCheckKey,
131
132
  parseCyvest: () => parseCyvest,
133
+ parseFindingKey: () => parseFindingKey,
132
134
  parseKeyType: () => parseKeyType,
133
135
  parseObservableKey: () => parseObservableKey,
134
136
  parseThreatIntelKey: () => parseThreatIntelKey,
135
- sortChecksByLevel: () => sortChecksByLevel,
136
- sortChecksByScore: () => sortChecksByScore,
137
+ sortFindingsByLevel: () => sortFindingsByLevel,
138
+ sortFindingsByScore: () => sortFindingsByScore,
137
139
  sortObservablesByLevel: () => sortObservablesByLevel,
138
140
  sortObservablesByScore: () => sortObservablesByScore,
139
141
  validateKey: () => validateKey
@@ -238,69 +240,6 @@ var cyvest_schema_default = {
238
240
  title: "AuditEvent",
239
241
  type: "object"
240
242
  },
241
- Check: {
242
- description: "Represents a verification step in the investigation.\n\nA check validates a specific aspect of the data under investigation\nand contributes to the overall investigation score.",
243
- properties: {
244
- check_name: {
245
- title: "Check Name",
246
- type: "string"
247
- },
248
- description: {
249
- title: "Description",
250
- type: "string"
251
- },
252
- comment: {
253
- title: "Comment",
254
- type: "string"
255
- },
256
- extra: {
257
- additionalProperties: true,
258
- title: "Extra",
259
- type: "object"
260
- },
261
- score: {
262
- title: "Score",
263
- type: "number"
264
- },
265
- level: {
266
- $ref: "#/$defs/Level"
267
- },
268
- origin_investigation_id: {
269
- title: "Origin Investigation Id",
270
- type: "string"
271
- },
272
- observable_links: {
273
- items: {
274
- $ref: "#/$defs/ObservableLink"
275
- },
276
- title: "Observable Links",
277
- type: "array"
278
- },
279
- key: {
280
- title: "Key",
281
- type: "string"
282
- },
283
- score_display: {
284
- readOnly: true,
285
- title: "Score Display",
286
- type: "string"
287
- }
288
- },
289
- required: [
290
- "check_name",
291
- "description",
292
- "comment",
293
- "extra",
294
- "score",
295
- "level",
296
- "origin_investigation_id",
297
- "observable_links",
298
- "key",
299
- "score_display"
300
- ],
301
- title: "Check",
302
- type: "object"
303
- },
304
243
  DataExtractionSchema: {
305
244
  additionalProperties: false,
306
245
  description: "Schema for data extraction metadata.",
@@ -361,6 +300,182 @@ var cyvest_schema_default = {
361
300
  title: "Enrichment",
362
301
  type: "object"
363
302
  },
303
+ Evidence: {
304
+ description: "Structured material supporting one or more findings.",
305
+ properties: {
306
+ type: {
307
+ title: "Type",
308
+ type: "string"
309
+ },
310
+ title: {
311
+ title: "Title",
312
+ type: "string"
313
+ },
314
+ description: {
315
+ title: "Description",
316
+ type: "string"
317
+ },
318
+ source: {
319
+ title: "Source",
320
+ type: "string"
321
+ },
322
+ external_id: {
323
+ anyOf: [
324
+ {
325
+ type: "string"
326
+ },
327
+ {
328
+ type: "null"
329
+ }
330
+ ],
331
+ title: "External Id"
332
+ },
333
+ content: {
334
+ anyOf: [
335
+ {},
336
+ {
337
+ type: "null"
338
+ }
339
+ ],
340
+ title: "Content"
341
+ },
342
+ uri: {
343
+ anyOf: [
344
+ {
345
+ type: "string"
346
+ },
347
+ {
348
+ type: "null"
349
+ }
350
+ ],
351
+ title: "Uri"
352
+ },
353
+ captured_at: {
354
+ format: "date-time",
355
+ title: "Captured At",
356
+ type: "string"
357
+ },
358
+ extra: {
359
+ additionalProperties: true,
360
+ title: "Extra",
361
+ type: "object"
362
+ },
363
+ key: {
364
+ title: "Key",
365
+ type: "string"
366
+ },
367
+ finding_links: {
368
+ description: "Findings that currently link to this evidence (navigation-only).",
369
+ items: {
370
+ type: "string"
371
+ },
372
+ readOnly: true,
373
+ title: "Finding Links",
374
+ type: "array"
375
+ }
376
+ },
377
+ required: [
378
+ "type",
379
+ "title",
380
+ "description",
381
+ "source",
382
+ "external_id",
383
+ "content",
384
+ "uri",
385
+ "captured_at",
386
+ "extra",
387
+ "key",
388
+ "finding_links"
389
+ ],
390
+ title: "Evidence",
391
+ type: "object"
392
+ },
393
+ EvidenceLink: {
394
+ additionalProperties: false,
395
+ description: "Edge metadata for a Finding\u2194Evidence association.",
396
+ properties: {
397
+ evidence_key: {
398
+ title: "Evidence Key",
399
+ type: "string"
400
+ }
401
+ },
402
+ required: [
403
+ "evidence_key"
404
+ ],
405
+ title: "EvidenceLink",
406
+ type: "object"
407
+ },
408
+ Finding: {
409
+ description: "Represents a verification step in the investigation.\n\nA finding validates a specific aspect of the data under investigation\nand contributes to the overall investigation score.",
410
+ properties: {
411
+ finding_name: {
412
+ title: "Finding Name",
413
+ type: "string"
414
+ },
415
+ description: {
416
+ title: "Description",
417
+ type: "string"
418
+ },
419
+ comment: {
420
+ title: "Comment",
421
+ type: "string"
422
+ },
423
+ extra: {
424
+ additionalProperties: true,
425
+ title: "Extra",
426
+ type: "object"
427
+ },
428
+ score: {
429
+ title: "Score",
430
+ type: "number"
431
+ },
432
+ level: {
433
+ $ref: "#/$defs/Level"
434
+ },
435
+ origin_investigation_id: {
436
+ title: "Origin Investigation Id",
437
+ type: "string"
438
+ },
439
+ observable_links: {
440
+ items: {
441
+ $ref: "#/$defs/ObservableLink"
442
+ },
443
+ title: "Observable Links",
444
+ type: "array"
445
+ },
446
+ evidence_links: {
447
+ items: {
448
+ $ref: "#/$defs/EvidenceLink"
449
+ },
450
+ title: "Evidence Links",
451
+ type: "array"
452
+ },
453
+ key: {
454
+ title: "Key",
455
+ type: "string"
456
+ },
457
+ score_display: {
458
+ readOnly: true,
459
+ title: "Score Display",
460
+ type: "string"
461
+ }
462
+ },
463
+ required: [
464
+ "finding_name",
465
+ "description",
466
+ "comment",
467
+ "extra",
468
+ "score",
469
+ "level",
470
+ "origin_investigation_id",
471
+ "observable_links",
472
+ "evidence_links",
473
+ "key",
474
+ "score_display"
475
+ ],
476
+ title: "Finding",
477
+ type: "object"
478
+ },
364
479
  InvestigationWhitelist: {
365
480
  description: "Represents a whitelist entry on an investigation.",
366
481
  properties: {
@@ -395,7 +510,7 @@ var cyvest_schema_default = {
395
510
  type: "object"
396
511
  },
397
512
  Level: {
398
- description: "Security level classification for checks, observables, and threat intelligence.\n\nLevels are ordered from lowest (NONE) to highest (MALICIOUS) severity.",
513
+ description: "Security level classification for findings, observables, and threat intelligence.\n\nLevels are ordered from lowest (NONE) to highest (MALICIOUS) severity.",
399
514
  enum: [
400
515
  "NONE",
401
516
  "TRUSTED",
@@ -409,12 +524,35 @@ var cyvest_schema_default = {
409
524
  type: "string"
410
525
  },
411
526
  Observable: {
412
- description: "Represents a cyber observable (IP, URL, domain, hash, etc.).\n\nObservables can be linked to threat intelligence, checks, and other observables\nthrough relationships.",
527
+ description: "Represents a cyber observable (IP, URL, domain, hash, etc.).\n\nObservables can be linked to threat intelligence, findings, and other observables\nthrough relationships.",
413
528
  properties: {
414
529
  type: {
415
530
  title: "Type",
416
531
  type: "string"
417
532
  },
533
+ subtype: {
534
+ anyOf: [
535
+ {
536
+ type: "string"
537
+ },
538
+ {
539
+ type: "null"
540
+ }
541
+ ],
542
+ title: "Subtype"
543
+ },
544
+ namespace: {
545
+ anyOf: [
546
+ {
547
+ type: "string"
548
+ },
549
+ {
550
+ type: "null"
551
+ }
552
+ ],
553
+ default: null,
554
+ title: "Namespace"
555
+ },
418
556
  value: {
419
557
  title: "Value",
420
558
  type: "string"
@@ -461,13 +599,13 @@ var cyvest_schema_default = {
461
599
  title: "Key",
462
600
  type: "string"
463
601
  },
464
- check_links: {
465
- description: "Checks that currently link to this observable (navigation-only).",
602
+ finding_links: {
603
+ description: "Findings that currently link to this observable (navigation-only).",
466
604
  items: {
467
605
  type: "string"
468
606
  },
469
607
  readOnly: true,
470
- title: "Check Links",
608
+ title: "Finding Links",
471
609
  type: "array"
472
610
  },
473
611
  score_display: {
@@ -488,7 +626,7 @@ var cyvest_schema_default = {
488
626
  "threat_intels",
489
627
  "relationships",
490
628
  "key",
491
- "check_links",
629
+ "finding_links",
492
630
  "score_display"
493
631
  ],
494
632
  title: "Observable",
@@ -496,7 +634,7 @@ var cyvest_schema_default = {
496
634
  },
497
635
  ObservableLink: {
498
636
  additionalProperties: false,
499
- description: "Edge metadata for a Check\u2194Observable association.",
637
+ description: "Edge metadata for a Finding\u2194Observable association.",
500
638
  properties: {
501
639
  observable_key: {
502
640
  title: "Observable Key",
@@ -514,7 +652,7 @@ var cyvest_schema_default = {
514
652
  type: "object"
515
653
  },
516
654
  PropagationMode: {
517
- description: "Controls how a Check\u2194Observable link propagates across merged investigations.",
655
+ description: "Controls how a Finding\u2194Observable link propagates across merged investigations.",
518
656
  enum: [
519
657
  "LOCAL_ONLY",
520
658
  "GLOBAL"
@@ -615,24 +753,45 @@ var cyvest_schema_default = {
615
753
  title: "Observables By Type And Level",
616
754
  type: "object"
617
755
  },
618
- total_checks: {
756
+ total_findings: {
619
757
  minimum: 0,
620
- title: "Total Checks",
758
+ title: "Total Findings",
621
759
  type: "integer"
622
760
  },
623
- applied_checks: {
761
+ applied_findings: {
624
762
  minimum: 0,
625
- title: "Applied Checks",
763
+ title: "Applied Findings",
626
764
  type: "integer"
627
765
  },
628
- checks_by_level: {
766
+ findings_by_level: {
629
767
  additionalProperties: {
630
768
  items: {
631
769
  type: "string"
632
770
  },
633
771
  type: "array"
634
772
  },
635
- title: "Checks By Level",
773
+ title: "Findings By Level",
774
+ type: "object"
775
+ },
776
+ total_evidences: {
777
+ minimum: 0,
778
+ title: "Total Evidences",
779
+ type: "integer"
780
+ },
781
+ evidences_by_type: {
782
+ additionalProperties: {
783
+ minimum: 0,
784
+ type: "integer"
785
+ },
786
+ title: "Evidences By Type",
787
+ type: "object"
788
+ },
789
+ evidences_by_source: {
790
+ additionalProperties: {
791
+ minimum: 0,
792
+ type: "integer"
793
+ },
794
+ title: "Evidences By Source",
636
795
  type: "object"
637
796
  },
638
797
  total_threat_intel: {
@@ -667,8 +826,9 @@ var cyvest_schema_default = {
667
826
  "internal_observables",
668
827
  "external_observables",
669
828
  "whitelisted_observables",
670
- "total_checks",
671
- "applied_checks",
829
+ "total_findings",
830
+ "applied_findings",
831
+ "total_evidences",
672
832
  "total_threat_intel",
673
833
  "total_tags"
674
834
  ],
@@ -677,7 +837,7 @@ var cyvest_schema_default = {
677
837
  },
678
838
  Tag: {
679
839
  additionalProperties: false,
680
- description: 'Groups checks for categorical organization.\n\nTags allow structuring the investigation into logical sections\nwith aggregated scores and levels. Hierarchy is automatic based on\nthe ":" delimiter in tag names (e.g., "header:auth:dkim").',
840
+ description: 'Groups findings for categorical organization.\n\nTags allow structuring the investigation into logical sections\nwith aggregated scores and levels. Hierarchy is automatic based on\nthe ":" delimiter in tag names (e.g., "header:auth:dkim").',
681
841
  properties: {
682
842
  name: {
683
843
  title: "Name",
@@ -688,11 +848,11 @@ var cyvest_schema_default = {
688
848
  title: "Description",
689
849
  type: "string"
690
850
  },
691
- checks: {
851
+ findings: {
692
852
  items: {
693
853
  type: "string"
694
854
  },
695
- title: "Checks",
855
+ title: "Findings",
696
856
  type: "array"
697
857
  },
698
858
  key: {
@@ -700,20 +860,20 @@ var cyvest_schema_default = {
700
860
  type: "string"
701
861
  },
702
862
  direct_score: {
703
- description: "Calculate the score from direct checks only (no hierarchy).\n\nFor hierarchical aggregation (including descendant tags), use\nInvestigation.get_tag_aggregated_score() or TagProxy.get_aggregated_score().\n\nReturns:\n Total score from direct checks",
863
+ description: "Calculate the score from direct findings only (no hierarchy).\n\nFor hierarchical aggregation (including descendant tags), use\nInvestigation.get_tag_aggregated_score() or TagProxy.get_aggregated_score().\n\nReturns:\n Total score from direct findings",
704
864
  readOnly: true,
705
865
  title: "Direct Score",
706
866
  type: "number"
707
867
  },
708
868
  direct_level: {
709
869
  $ref: "#/$defs/Level",
710
- description: "Calculate the level from direct checks only (no hierarchy).\n\nFor hierarchical aggregation (including descendant tags), use\nInvestigation.get_tag_aggregated_level() or TagProxy.get_aggregated_level().\n\nReturns:\n Level based on direct score",
870
+ description: "Calculate the level from direct findings only (no hierarchy).\n\nFor hierarchical aggregation (including descendant tags), use\nInvestigation.get_tag_aggregated_level() or TagProxy.get_aggregated_level().\n\nReturns:\n Level based on direct score",
711
871
  readOnly: true
712
872
  }
713
873
  },
714
874
  required: [
715
875
  "name",
716
- "checks",
876
+ "findings",
717
877
  "key",
718
878
  "direct_score",
719
879
  "direct_level"
@@ -809,6 +969,12 @@ var cyvest_schema_default = {
809
969
  additionalProperties: false,
810
970
  description: "Schema for a complete serialized investigation.\n\nThis model describes the output of `serialize_investigation()` from\n`cyvest.io_serialization`. It is the top-level schema for exported investigations.\n\nEntity types reference the runtime models directly. When generating schemas with\n`mode='serialization'`, Pydantic respects field_serializer decorators and produces\nschemas matching the actual model_dump() output.",
811
971
  properties: {
972
+ schema_version: {
973
+ const: "6.0.0",
974
+ default: "6.0.0",
975
+ title: "Schema Version",
976
+ type: "string"
977
+ },
812
978
  investigation_id: {
813
979
  description: "Stable investigation identity (ULID).",
814
980
  title: "Investigation Id",
@@ -872,12 +1038,20 @@ var cyvest_schema_default = {
872
1038
  title: "Observables",
873
1039
  type: "object"
874
1040
  },
875
- checks: {
1041
+ findings: {
1042
+ additionalProperties: {
1043
+ $ref: "#/$defs/Finding"
1044
+ },
1045
+ description: "Findings keyed by their unique key.",
1046
+ title: "Findings",
1047
+ type: "object"
1048
+ },
1049
+ evidences: {
876
1050
  additionalProperties: {
877
- $ref: "#/$defs/Check"
1051
+ $ref: "#/$defs/Evidence"
878
1052
  },
879
- description: "Checks keyed by their unique key.",
880
- title: "Checks",
1053
+ description: "Evidence objects keyed by their unique key.",
1054
+ title: "Evidences",
881
1055
  type: "object"
882
1056
  },
883
1057
  threat_intels: {
@@ -926,7 +1100,8 @@ var cyvest_schema_default = {
926
1100
  "whitelisted",
927
1101
  "whitelists",
928
1102
  "observables",
929
- "checks",
1103
+ "findings",
1104
+ "evidences",
930
1105
  "threat_intels",
931
1106
  "enrichments",
932
1107
  "tags",
@@ -965,6 +1140,108 @@ function isCyvest(json) {
965
1140
  function normalizeValue(value) {
966
1141
  return value.trim().toLowerCase();
967
1142
  }
1143
+ function normalizeObservableValue(obsType, value, subtype) {
1144
+ const normalizedType = normalizeValue(obsType);
1145
+ const normalizedSubtype = subtype ? normalizeValue(subtype) : void 0;
1146
+ const stripped = value.trim();
1147
+ if (normalizedType === "command_line") return stripped;
1148
+ if (normalizedType === "email" || normalizedType === "host") {
1149
+ return stripped.toLowerCase();
1150
+ }
1151
+ if (normalizedType === "user" && (normalizedSubtype === "email" || normalizedSubtype === "upn")) {
1152
+ return stripped.toLowerCase();
1153
+ }
1154
+ if (normalizedSubtype === "uid" || normalizedSubtype === "pid") {
1155
+ if (!/^[+-]?\d+$/.test(stripped)) {
1156
+ throw new Error(`${normalizedSubtype} observable values must be base-10 integers`);
1157
+ }
1158
+ return BigInt(stripped).toString(10);
1159
+ }
1160
+ return stripped;
1161
+ }
1162
+ function sha256(content) {
1163
+ const bytes = new TextEncoder().encode(content);
1164
+ const words = [];
1165
+ const bitLength = bytes.length * 8;
1166
+ for (const byte of bytes) {
1167
+ words.push(byte);
1168
+ }
1169
+ words.push(128);
1170
+ while (words.length % 64 !== 56) words.push(0);
1171
+ for (let i = 7; i >= 0; i--) {
1172
+ words.push(Math.floor(bitLength / 2 ** (i * 8)) & 255);
1173
+ }
1174
+ const h = [
1175
+ 1779033703,
1176
+ 3144134277,
1177
+ 1013904242,
1178
+ 2773480762,
1179
+ 1359893119,
1180
+ 2600822924,
1181
+ 528734635,
1182
+ 1541459225
1183
+ ];
1184
+ const k = Array.from({ length: 64 }, (_, index) => {
1185
+ let primeCount = 0;
1186
+ let candidate = 2;
1187
+ while (true) {
1188
+ let prime = true;
1189
+ for (let divisor = 2; divisor * divisor <= candidate; divisor++) {
1190
+ if (candidate % divisor === 0) {
1191
+ prime = false;
1192
+ break;
1193
+ }
1194
+ }
1195
+ if (prime && primeCount++ === index) {
1196
+ return Math.floor(Math.cbrt(candidate) % 1 * 2 ** 32) >>> 0;
1197
+ }
1198
+ candidate++;
1199
+ }
1200
+ });
1201
+ const rotateRight = (value, amount) => value >>> amount | value << 32 - amount;
1202
+ for (let offset = 0; offset < words.length; offset += 64) {
1203
+ const schedule = new Array(64);
1204
+ for (let i = 0; i < 16; i++) {
1205
+ const base = offset + i * 4;
1206
+ schedule[i] = (words[base] << 24 | words[base + 1] << 16 | words[base + 2] << 8 | words[base + 3]) >>> 0;
1207
+ }
1208
+ for (let i = 16; i < 64; i++) {
1209
+ const s0 = rotateRight(schedule[i - 15], 7) ^ rotateRight(schedule[i - 15], 18) ^ schedule[i - 15] >>> 3;
1210
+ const s1 = rotateRight(schedule[i - 2], 17) ^ rotateRight(schedule[i - 2], 19) ^ schedule[i - 2] >>> 10;
1211
+ schedule[i] = schedule[i - 16] + s0 + schedule[i - 7] + s1 >>> 0;
1212
+ }
1213
+ let [a, b, c, d, e, f, g, hh] = h;
1214
+ for (let i = 0; i < 64; i++) {
1215
+ const s1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25);
1216
+ const choice = e & f ^ ~e & g;
1217
+ const temp1 = hh + s1 + choice + k[i] + schedule[i] >>> 0;
1218
+ const s0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22);
1219
+ const majority = a & b ^ a & c ^ b & c;
1220
+ const temp2 = s0 + majority >>> 0;
1221
+ hh = g;
1222
+ g = f;
1223
+ f = e;
1224
+ e = d + temp1 >>> 0;
1225
+ d = c;
1226
+ c = b;
1227
+ b = a;
1228
+ a = temp1 + temp2 >>> 0;
1229
+ }
1230
+ [a, b, c, d, e, f, g, hh].forEach((value, index) => {
1231
+ h[index] = h[index] + value >>> 0;
1232
+ });
1233
+ }
1234
+ return h.map((value) => value.toString(16).padStart(8, "0")).join("");
1235
+ }
1236
+ function encodeKeyPart(value, keepSlash = false) {
1237
+ let encoded = encodeURIComponent(value).replace(
1238
+ /[!'()*]/g,
1239
+ (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`
1240
+ );
1241
+ encoded = encoded.replace(/%40/gi, "@");
1242
+ if (keepSlash) encoded = encoded.replace(/%2F/gi, "/").replace(/%5C/gi, "\\");
1243
+ return encoded;
1244
+ }
968
1245
  function hashString(content, length = 16) {
969
1246
  let hash = 0;
970
1247
  for (let i = 0; i < content.length; i++) {
@@ -974,14 +1251,35 @@ function hashString(content, length = 16) {
974
1251
  const hex = Math.abs(hash).toString(16).padStart(8, "0");
975
1252
  return hex.slice(0, length);
976
1253
  }
977
- function generateObservableKey(obsType, value) {
1254
+ function generateObservableKey(obsType, value, subtype, namespace) {
978
1255
  const normalizedType = normalizeValue(obsType);
979
- const normalizedValue = normalizeValue(value);
980
- return `obs:${normalizedType}:${normalizedValue}`;
1256
+ const normalizedSubtype = subtype ? normalizeValue(subtype) : void 0;
1257
+ const normalizedNamespace = namespace?.trim().toLowerCase() || void 0;
1258
+ const normalizedValue = normalizeObservableValue(
1259
+ normalizedType,
1260
+ value,
1261
+ normalizedSubtype
1262
+ );
1263
+ const identity = JSON.stringify({
1264
+ namespace: normalizedNamespace ?? null,
1265
+ subtype: normalizedSubtype ?? null,
1266
+ type: normalizedType,
1267
+ value: normalizedValue
1268
+ });
1269
+ if (normalizedType === "command_line" || new TextEncoder().encode(identity).length > 128) {
1270
+ return `obs:${normalizedType}:sha256:${sha256(identity)}`;
1271
+ }
1272
+ if (!normalizedSubtype && !normalizedNamespace) {
1273
+ return `obs:${normalizedType}:${normalizedValue.toLowerCase()}`;
1274
+ }
1275
+ const parts = ["obs", encodeKeyPart(normalizedType), normalizedSubtype ? encodeKeyPart(normalizedSubtype) : "_"];
1276
+ if (normalizedNamespace) parts.push(encodeKeyPart(normalizedNamespace));
1277
+ parts.push(encodeKeyPart(normalizedValue, true));
1278
+ return parts.join(":");
981
1279
  }
982
- function generateCheckKey(checkName) {
983
- const normalizedName = normalizeValue(checkName);
984
- return `chk:${normalizedName}`;
1280
+ function generateFindingKey(findingName) {
1281
+ const normalizedName = normalizeValue(findingName);
1282
+ return `fnd:${normalizedName}`;
985
1283
  }
986
1284
  function generateThreatIntelKey(source, observableKey) {
987
1285
  const normalizedSource = normalizeValue(source);
@@ -1020,7 +1318,7 @@ function isTagDescendantOf(descendantName, ancestorName) {
1020
1318
  function parseKeyType(key) {
1021
1319
  if (key.includes(":")) {
1022
1320
  const prefix = key.split(":", 1)[0];
1023
- if (["obs", "chk", "ti", "enr", "tag"].includes(prefix)) {
1321
+ if (["obs", "fnd", "evd", "ti", "enr", "tag"].includes(prefix)) {
1024
1322
  return prefix;
1025
1323
  }
1026
1324
  }
@@ -1053,14 +1351,14 @@ function parseObservableKey(key) {
1053
1351
  }
1054
1352
  return null;
1055
1353
  }
1056
- function parseCheckKey(key) {
1057
- if (!validateKey(key, "chk")) {
1354
+ function parseFindingKey(key) {
1355
+ if (!validateKey(key, "fnd")) {
1058
1356
  return null;
1059
1357
  }
1060
1358
  const parts = key.split(":");
1061
1359
  if (parts.length >= 2) {
1062
1360
  return {
1063
- checkName: parts.slice(1).join(":")
1361
+ findingName: parts.slice(1).join(":")
1064
1362
  };
1065
1363
  }
1066
1364
  return null;
@@ -1193,15 +1491,8 @@ function getEntityLevel(entity) {
1193
1491
  function getObservable(inv, key) {
1194
1492
  return inv.observables[key];
1195
1493
  }
1196
- function getObservableByTypeValue(inv, type, value) {
1197
- const normalizedType = type.trim().toLowerCase();
1198
- const normalizedValue = value.trim().toLowerCase();
1199
- for (const obs of Object.values(inv.observables)) {
1200
- if (obs.type.toLowerCase() === normalizedType && obs.value.toLowerCase() === normalizedValue) {
1201
- return obs;
1202
- }
1203
- }
1204
- return void 0;
1494
+ function getObservableByTypeValue(inv, type, value, subtype, namespace) {
1495
+ return inv.observables[generateObservableKey(type, value, subtype, namespace)];
1205
1496
  }
1206
1497
  function getRootObservable(inv) {
1207
1498
  const rootType = inv.data_extraction.root_type;
@@ -1211,15 +1502,21 @@ function getRootObservable(inv) {
1211
1502
  const rootKey = generateObservableKey(rootType, "root");
1212
1503
  return inv.observables[rootKey];
1213
1504
  }
1214
- function getCheck(inv, key) {
1215
- return inv.checks[key];
1505
+ function getFinding(inv, key) {
1506
+ return inv.findings[key];
1507
+ }
1508
+ function getFindingByName(inv, findingName) {
1509
+ const key = generateFindingKey(findingName);
1510
+ return inv.findings[key];
1511
+ }
1512
+ function getAllFindings(inv) {
1513
+ return Object.values(inv.findings);
1216
1514
  }
1217
- function getCheckByName(inv, checkName) {
1218
- const key = generateCheckKey(checkName);
1219
- return inv.checks[key];
1515
+ function getEvidence(inv, key) {
1516
+ return inv.evidences[key];
1220
1517
  }
1221
- function getAllChecks(inv) {
1222
- return Object.values(inv.checks);
1518
+ function getAllEvidences(inv) {
1519
+ return Object.values(inv.evidences);
1223
1520
  }
1224
1521
  function getThreatIntel(inv, key) {
1225
1522
  return inv.threat_intels[key];
@@ -1276,7 +1573,8 @@ function getDataExtraction(inv) {
1276
1573
  function getCounts(inv) {
1277
1574
  return {
1278
1575
  observables: Object.keys(inv.observables).length,
1279
- checks: getAllChecks(inv).length,
1576
+ findings: getAllFindings(inv).length,
1577
+ evidences: getAllEvidences(inv).length,
1280
1578
  threatIntels: Object.keys(inv.threat_intels).length,
1281
1579
  enrichments: Object.keys(inv.enrichments).length,
1282
1580
  tags: getAllTags(inv).length,
@@ -1358,18 +1656,18 @@ function findObservablesWithThreatIntel(inv) {
1358
1656
  (obs) => obs.threat_intels.length > 0
1359
1657
  );
1360
1658
  }
1361
- function findChecksByLevel(inv, level) {
1362
- return Object.values(inv.checks).filter((check) => check.level === level);
1659
+ function findFindingsByLevel(inv, level) {
1660
+ return Object.values(inv.findings).filter((finding) => finding.level === level);
1363
1661
  }
1364
- function findChecksAtLeast(inv, minLevel2) {
1365
- return Object.values(inv.checks).filter(
1366
- (check) => isLevelAtLeast(check.level, minLevel2)
1662
+ function findFindingsAtLeast(inv, minLevel2) {
1663
+ return Object.values(inv.findings).filter(
1664
+ (finding) => isLevelAtLeast(finding.level, minLevel2)
1367
1665
  );
1368
1666
  }
1369
- function findCheckByName(inv, checkName) {
1370
- const normalizedName = checkName.trim().toLowerCase();
1371
- return Object.values(inv.checks).find(
1372
- (check) => check.check_name.toLowerCase() === normalizedName
1667
+ function findFindingByName(inv, findingName) {
1668
+ const normalizedName = findingName.trim().toLowerCase();
1669
+ return Object.values(inv.findings).find(
1670
+ (finding) => finding.finding_name.toLowerCase() === normalizedName
1373
1671
  );
1374
1672
  }
1375
1673
  function findThreatIntelBySource(inv, source) {
@@ -1397,26 +1695,26 @@ function findTagsAtLeast(inv, minLevel2) {
1397
1695
  function findTagsByNamePattern(inv, pattern) {
1398
1696
  return Object.values(inv.tags).filter((tag) => pattern.test(tag.name));
1399
1697
  }
1400
- function findChecksForObservable(inv, observableKey) {
1698
+ function findFindingsForObservable(inv, observableKey) {
1401
1699
  const result = [];
1402
1700
  const seen = /* @__PURE__ */ new Set();
1403
1701
  const observable = inv.observables[observableKey];
1404
1702
  if (observable) {
1405
- for (const checkKey of observable.check_links) {
1406
- const check = inv.checks[checkKey];
1407
- if (check && !seen.has(check.key)) {
1408
- result.push(check);
1409
- seen.add(check.key);
1703
+ for (const findingKey of observable.finding_links) {
1704
+ const finding = inv.findings[findingKey];
1705
+ if (finding && !seen.has(finding.key)) {
1706
+ result.push(finding);
1707
+ seen.add(finding.key);
1410
1708
  }
1411
1709
  }
1412
1710
  }
1413
- for (const check of Object.values(inv.checks)) {
1414
- if (seen.has(check.key)) {
1711
+ for (const finding of Object.values(inv.findings)) {
1712
+ if (seen.has(finding.key)) {
1415
1713
  continue;
1416
1714
  }
1417
- if (check.observable_links.some((link) => link.observable_key === observableKey)) {
1418
- result.push(check);
1419
- seen.add(check.key);
1715
+ if (finding.observable_links.some((link) => link.observable_key === observableKey)) {
1716
+ result.push(finding);
1717
+ seen.add(finding.key);
1420
1718
  }
1421
1719
  }
1422
1720
  return result;
@@ -1430,37 +1728,37 @@ function findThreatIntelsForObservable(inv, observableKey) {
1430
1728
  (ti) => ti.observable_key === observableKey
1431
1729
  );
1432
1730
  }
1433
- function findObservablesForCheck(inv, checkKey) {
1434
- const check = inv.checks[checkKey];
1435
- if (check) {
1731
+ function findObservablesForFinding(inv, findingKey) {
1732
+ const finding = inv.findings[findingKey];
1733
+ if (finding) {
1436
1734
  const keys = /* @__PURE__ */ new Set();
1437
- for (const link of check.observable_links) {
1735
+ for (const link of finding.observable_links) {
1438
1736
  keys.add(link.observable_key);
1439
1737
  }
1440
1738
  return Array.from(keys).map((obsKey) => inv.observables[obsKey]).filter((obs) => obs !== void 0);
1441
1739
  }
1442
1740
  return [];
1443
1741
  }
1444
- function findChecksForTag(inv, tagKey, recursive = false) {
1742
+ function findFindingsForTag(inv, tagKey, recursive = false) {
1445
1743
  const result = [];
1446
1744
  const tag = inv.tags[tagKey];
1447
1745
  if (!tag) {
1448
1746
  return result;
1449
1747
  }
1450
- for (const checkKey of tag.checks) {
1451
- const check = inv.checks[checkKey];
1452
- if (check) {
1453
- result.push(check);
1748
+ for (const findingKey of tag.findings) {
1749
+ const finding = inv.findings[findingKey];
1750
+ if (finding) {
1751
+ result.push(finding);
1454
1752
  }
1455
1753
  }
1456
1754
  if (recursive) {
1457
1755
  const prefix = tag.name + ":";
1458
1756
  for (const otherTag of Object.values(inv.tags)) {
1459
1757
  if (otherTag.name.startsWith(prefix)) {
1460
- for (const checkKey of otherTag.checks) {
1461
- const check = inv.checks[checkKey];
1462
- if (check) {
1463
- result.push(check);
1758
+ for (const findingKey of otherTag.findings) {
1759
+ const finding = inv.findings[findingKey];
1760
+ if (finding) {
1761
+ result.push(finding);
1464
1762
  }
1465
1763
  }
1466
1764
  }
@@ -1471,24 +1769,24 @@ function findChecksForTag(inv, tagKey, recursive = false) {
1471
1769
  function sortObservablesByScore(observables) {
1472
1770
  return [...observables].sort((a, b) => b.score - a.score);
1473
1771
  }
1474
- function sortChecksByScore(checks) {
1475
- return [...checks].sort((a, b) => b.score - a.score);
1772
+ function sortFindingsByScore(findings) {
1773
+ return [...findings].sort((a, b) => b.score - a.score);
1476
1774
  }
1477
1775
  function sortObservablesByLevel(observables) {
1478
1776
  return [...observables].sort(
1479
1777
  (a, b) => LEVEL_VALUES[b.level] - LEVEL_VALUES[a.level]
1480
1778
  );
1481
1779
  }
1482
- function sortChecksByLevel(checks) {
1483
- return [...checks].sort(
1780
+ function sortFindingsByLevel(findings) {
1781
+ return [...findings].sort(
1484
1782
  (a, b) => LEVEL_VALUES[b.level] - LEVEL_VALUES[a.level]
1485
1783
  );
1486
1784
  }
1487
1785
  function findHighestScoringObservables(inv, n = 10) {
1488
1786
  return sortObservablesByScore(Object.values(inv.observables)).slice(0, n);
1489
1787
  }
1490
- function findHighestScoringChecks(inv, n = 10) {
1491
- return sortChecksByScore(Object.values(inv.checks)).slice(0, n);
1788
+ function findHighestScoringFindings(inv, n = 10) {
1789
+ return sortFindingsByScore(Object.values(inv.findings)).slice(0, n);
1492
1790
  }
1493
1791
  function findMaliciousObservables(inv) {
1494
1792
  return findObservablesByLevel(inv, "MALICIOUS");
@@ -1496,14 +1794,14 @@ function findMaliciousObservables(inv) {
1496
1794
  function findSuspiciousObservables(inv) {
1497
1795
  return findObservablesByLevel(inv, "SUSPICIOUS");
1498
1796
  }
1499
- function findMaliciousChecks(inv) {
1500
- return findChecksByLevel(inv, "MALICIOUS");
1797
+ function findMaliciousFindings(inv) {
1798
+ return findFindingsByLevel(inv, "MALICIOUS");
1501
1799
  }
1502
- function findSuspiciousChecks(inv) {
1503
- return findChecksByLevel(inv, "SUSPICIOUS");
1800
+ function findSuspiciousFindings(inv) {
1801
+ return findFindingsByLevel(inv, "SUSPICIOUS");
1504
1802
  }
1505
- function getAllCheckKeys(inv) {
1506
- return Object.keys(inv.checks);
1803
+ function getAllFindingKeys(inv) {
1804
+ return Object.keys(inv.findings);
1507
1805
  }
1508
1806
  function getAllObservableTypes(inv) {
1509
1807
  const types = /* @__PURE__ */ new Set();
@@ -1788,30 +2086,30 @@ function getRelationshipsForObservable(inv, observableKey) {
1788
2086
  areConnected,
1789
2087
  compareLevels,
1790
2088
  countRelationshipsByType,
1791
- findCheckByName,
1792
- findChecksAtLeast,
1793
- findChecksByLevel,
1794
- findChecksForObservable,
1795
- findChecksForTag,
1796
2089
  findExternalObservables,
1797
- findHighestScoringChecks,
2090
+ findFindingByName,
2091
+ findFindingsAtLeast,
2092
+ findFindingsByLevel,
2093
+ findFindingsForObservable,
2094
+ findFindingsForTag,
2095
+ findHighestScoringFindings,
1798
2096
  findHighestScoringObservables,
1799
2097
  findInternalObservables,
1800
2098
  findLeafObservables,
1801
- findMaliciousChecks,
2099
+ findMaliciousFindings,
1802
2100
  findMaliciousObservables,
1803
2101
  findObservablesAtLeast,
1804
2102
  findObservablesByLevel,
1805
2103
  findObservablesByType,
1806
2104
  findObservablesByValue,
1807
2105
  findObservablesContaining,
1808
- findObservablesForCheck,
2106
+ findObservablesForFinding,
1809
2107
  findObservablesMatching,
1810
2108
  findObservablesWithThreatIntel,
1811
2109
  findOrphanObservables,
1812
2110
  findPath,
1813
2111
  findSourceObservables,
1814
- findSuspiciousChecks,
2112
+ findSuspiciousFindings,
1815
2113
  findSuspiciousObservables,
1816
2114
  findTagsAtLeast,
1817
2115
  findTagsByLevel,
@@ -1821,22 +2119,21 @@ function getRelationshipsForObservable(inv, observableKey) {
1821
2119
  findThreatIntelBySource,
1822
2120
  findThreatIntelsForObservable,
1823
2121
  findWhitelistedObservables,
1824
- generateCheckKey,
1825
2122
  generateEnrichmentKey,
2123
+ generateFindingKey,
1826
2124
  generateObservableKey,
1827
2125
  generateTagKey,
1828
2126
  generateThreatIntelKey,
1829
- getAllCheckKeys,
1830
- getAllChecks,
1831
2127
  getAllEnrichments,
2128
+ getAllEvidences,
2129
+ getAllFindingKeys,
2130
+ getAllFindings,
1832
2131
  getAllObservableTypes,
1833
2132
  getAllObservables,
1834
2133
  getAllRelationshipTypes,
1835
2134
  getAllTags,
1836
2135
  getAllThreatIntelSources,
1837
2136
  getAllThreatIntels,
1838
- getCheck,
1839
- getCheckByName,
1840
2137
  getColorForLevel,
1841
2138
  getColorForScore,
1842
2139
  getCounts,
@@ -1844,6 +2141,9 @@ function getRelationshipsForObservable(inv, observableKey) {
1844
2141
  getEnrichment,
1845
2142
  getEnrichmentByName,
1846
2143
  getEntityLevel,
2144
+ getEvidence,
2145
+ getFinding,
2146
+ getFindingByName,
1847
2147
  getLevelFromScore,
1848
2148
  getObservable,
1849
2149
  getObservableByTypeValue,
@@ -1879,13 +2179,13 @@ function getRelationshipsForObservable(inv, observableKey) {
1879
2179
  maxLevel,
1880
2180
  minLevel,
1881
2181
  normalizeLevel,
1882
- parseCheckKey,
1883
2182
  parseCyvest,
2183
+ parseFindingKey,
1884
2184
  parseKeyType,
1885
2185
  parseObservableKey,
1886
2186
  parseThreatIntelKey,
1887
- sortChecksByLevel,
1888
- sortChecksByScore,
2187
+ sortFindingsByLevel,
2188
+ sortFindingsByScore,
1889
2189
  sortObservablesByLevel,
1890
2190
  sortObservablesByScore,
1891
2191
  validateKey