@cyvest/cyvest-js 5.4.1 → 6.1.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"
@@ -443,6 +581,19 @@ var cyvest_schema_default = {
443
581
  level: {
444
582
  $ref: "#/$defs/Level"
445
583
  },
584
+ aliases: {
585
+ items: {
586
+ $ref: "#/$defs/ObservableAlias"
587
+ },
588
+ title: "Aliases",
589
+ type: "array"
590
+ },
591
+ occurrence_count: {
592
+ default: 1,
593
+ minimum: 1,
594
+ title: "Occurrence Count",
595
+ type: "integer"
596
+ },
446
597
  threat_intels: {
447
598
  items: {
448
599
  type: "string"
@@ -461,13 +612,13 @@ var cyvest_schema_default = {
461
612
  title: "Key",
462
613
  type: "string"
463
614
  },
464
- check_links: {
465
- description: "Checks that currently link to this observable (navigation-only).",
615
+ finding_links: {
616
+ description: "Findings that currently link to this observable (navigation-only).",
466
617
  items: {
467
618
  type: "string"
468
619
  },
469
620
  readOnly: true,
470
- title: "Check Links",
621
+ title: "Finding Links",
471
622
  type: "array"
472
623
  },
473
624
  score_display: {
@@ -485,18 +636,67 @@ var cyvest_schema_default = {
485
636
  "extra",
486
637
  "score",
487
638
  "level",
639
+ "aliases",
488
640
  "threat_intels",
489
641
  "relationships",
490
642
  "key",
491
- "check_links",
643
+ "finding_links",
492
644
  "score_display"
493
645
  ],
494
646
  title: "Observable",
495
647
  type: "object"
496
648
  },
649
+ ObservableAlias: {
650
+ description: "Source observable identity attached to a canonical observable.",
651
+ properties: {
652
+ type: {
653
+ title: "Type",
654
+ type: "string"
655
+ },
656
+ subtype: {
657
+ anyOf: [
658
+ {
659
+ type: "string"
660
+ },
661
+ {
662
+ type: "null"
663
+ }
664
+ ],
665
+ title: "Subtype"
666
+ },
667
+ namespace: {
668
+ anyOf: [
669
+ {
670
+ type: "string"
671
+ },
672
+ {
673
+ type: "null"
674
+ }
675
+ ],
676
+ default: null,
677
+ title: "Namespace"
678
+ },
679
+ value: {
680
+ title: "Value",
681
+ type: "string"
682
+ },
683
+ count: {
684
+ default: 1,
685
+ minimum: 1,
686
+ title: "Count",
687
+ type: "integer"
688
+ }
689
+ },
690
+ required: [
691
+ "type",
692
+ "value"
693
+ ],
694
+ title: "ObservableAlias",
695
+ type: "object"
696
+ },
497
697
  ObservableLink: {
498
698
  additionalProperties: false,
499
- description: "Edge metadata for a Check\u2194Observable association.",
699
+ description: "Edge metadata for a Finding\u2194Observable association.",
500
700
  properties: {
501
701
  observable_key: {
502
702
  title: "Observable Key",
@@ -514,7 +714,7 @@ var cyvest_schema_default = {
514
714
  type: "object"
515
715
  },
516
716
  PropagationMode: {
517
- description: "Controls how a Check\u2194Observable link propagates across merged investigations.",
717
+ description: "Controls how a Finding\u2194Observable link propagates across merged investigations.",
518
718
  enum: [
519
719
  "LOCAL_ONLY",
520
720
  "GLOBAL"
@@ -615,24 +815,45 @@ var cyvest_schema_default = {
615
815
  title: "Observables By Type And Level",
616
816
  type: "object"
617
817
  },
618
- total_checks: {
818
+ total_findings: {
619
819
  minimum: 0,
620
- title: "Total Checks",
820
+ title: "Total Findings",
621
821
  type: "integer"
622
822
  },
623
- applied_checks: {
823
+ applied_findings: {
624
824
  minimum: 0,
625
- title: "Applied Checks",
825
+ title: "Applied Findings",
626
826
  type: "integer"
627
827
  },
628
- checks_by_level: {
828
+ findings_by_level: {
629
829
  additionalProperties: {
630
830
  items: {
631
831
  type: "string"
632
832
  },
633
833
  type: "array"
634
834
  },
635
- title: "Checks By Level",
835
+ title: "Findings By Level",
836
+ type: "object"
837
+ },
838
+ total_evidences: {
839
+ minimum: 0,
840
+ title: "Total Evidences",
841
+ type: "integer"
842
+ },
843
+ evidences_by_type: {
844
+ additionalProperties: {
845
+ minimum: 0,
846
+ type: "integer"
847
+ },
848
+ title: "Evidences By Type",
849
+ type: "object"
850
+ },
851
+ evidences_by_source: {
852
+ additionalProperties: {
853
+ minimum: 0,
854
+ type: "integer"
855
+ },
856
+ title: "Evidences By Source",
636
857
  type: "object"
637
858
  },
638
859
  total_threat_intel: {
@@ -667,8 +888,9 @@ var cyvest_schema_default = {
667
888
  "internal_observables",
668
889
  "external_observables",
669
890
  "whitelisted_observables",
670
- "total_checks",
671
- "applied_checks",
891
+ "total_findings",
892
+ "applied_findings",
893
+ "total_evidences",
672
894
  "total_threat_intel",
673
895
  "total_tags"
674
896
  ],
@@ -677,7 +899,7 @@ var cyvest_schema_default = {
677
899
  },
678
900
  Tag: {
679
901
  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").',
902
+ 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
903
  properties: {
682
904
  name: {
683
905
  title: "Name",
@@ -688,11 +910,11 @@ var cyvest_schema_default = {
688
910
  title: "Description",
689
911
  type: "string"
690
912
  },
691
- checks: {
913
+ findings: {
692
914
  items: {
693
915
  type: "string"
694
916
  },
695
- title: "Checks",
917
+ title: "Findings",
696
918
  type: "array"
697
919
  },
698
920
  key: {
@@ -700,20 +922,20 @@ var cyvest_schema_default = {
700
922
  type: "string"
701
923
  },
702
924
  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",
925
+ 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
926
  readOnly: true,
705
927
  title: "Direct Score",
706
928
  type: "number"
707
929
  },
708
930
  direct_level: {
709
931
  $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",
932
+ 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
933
  readOnly: true
712
934
  }
713
935
  },
714
936
  required: [
715
937
  "name",
716
- "checks",
938
+ "findings",
717
939
  "key",
718
940
  "direct_score",
719
941
  "direct_level"
@@ -809,6 +1031,12 @@ var cyvest_schema_default = {
809
1031
  additionalProperties: false,
810
1032
  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
1033
  properties: {
1034
+ schema_version: {
1035
+ const: "6.0.0",
1036
+ default: "6.0.0",
1037
+ title: "Schema Version",
1038
+ type: "string"
1039
+ },
812
1040
  investigation_id: {
813
1041
  description: "Stable investigation identity (ULID).",
814
1042
  title: "Investigation Id",
@@ -872,12 +1100,20 @@ var cyvest_schema_default = {
872
1100
  title: "Observables",
873
1101
  type: "object"
874
1102
  },
875
- checks: {
1103
+ findings: {
1104
+ additionalProperties: {
1105
+ $ref: "#/$defs/Finding"
1106
+ },
1107
+ description: "Findings keyed by their unique key.",
1108
+ title: "Findings",
1109
+ type: "object"
1110
+ },
1111
+ evidences: {
876
1112
  additionalProperties: {
877
- $ref: "#/$defs/Check"
1113
+ $ref: "#/$defs/Evidence"
878
1114
  },
879
- description: "Checks keyed by their unique key.",
880
- title: "Checks",
1115
+ description: "Evidence objects keyed by their unique key.",
1116
+ title: "Evidences",
881
1117
  type: "object"
882
1118
  },
883
1119
  threat_intels: {
@@ -926,7 +1162,8 @@ var cyvest_schema_default = {
926
1162
  "whitelisted",
927
1163
  "whitelists",
928
1164
  "observables",
929
- "checks",
1165
+ "findings",
1166
+ "evidences",
930
1167
  "threat_intels",
931
1168
  "enrichments",
932
1169
  "tags",
@@ -965,6 +1202,108 @@ function isCyvest(json) {
965
1202
  function normalizeValue(value) {
966
1203
  return value.trim().toLowerCase();
967
1204
  }
1205
+ function normalizeObservableValue(obsType, value, subtype) {
1206
+ const normalizedType = normalizeValue(obsType);
1207
+ const normalizedSubtype = subtype ? normalizeValue(subtype) : void 0;
1208
+ const stripped = value.trim();
1209
+ if (normalizedType === "command_line") return stripped;
1210
+ if (normalizedType === "email" || normalizedType === "host") {
1211
+ return stripped.toLowerCase();
1212
+ }
1213
+ if (normalizedType === "user" && (normalizedSubtype === "email" || normalizedSubtype === "upn")) {
1214
+ return stripped.toLowerCase();
1215
+ }
1216
+ if (normalizedSubtype === "uid" || normalizedSubtype === "pid") {
1217
+ if (!/^[+-]?\d+$/.test(stripped)) {
1218
+ throw new Error(`${normalizedSubtype} observable values must be base-10 integers`);
1219
+ }
1220
+ return BigInt(stripped).toString(10);
1221
+ }
1222
+ return stripped;
1223
+ }
1224
+ function sha256(content) {
1225
+ const bytes = new TextEncoder().encode(content);
1226
+ const words = [];
1227
+ const bitLength = bytes.length * 8;
1228
+ for (const byte of bytes) {
1229
+ words.push(byte);
1230
+ }
1231
+ words.push(128);
1232
+ while (words.length % 64 !== 56) words.push(0);
1233
+ for (let i = 7; i >= 0; i--) {
1234
+ words.push(Math.floor(bitLength / 2 ** (i * 8)) & 255);
1235
+ }
1236
+ const h = [
1237
+ 1779033703,
1238
+ 3144134277,
1239
+ 1013904242,
1240
+ 2773480762,
1241
+ 1359893119,
1242
+ 2600822924,
1243
+ 528734635,
1244
+ 1541459225
1245
+ ];
1246
+ const k = Array.from({ length: 64 }, (_, index) => {
1247
+ let primeCount = 0;
1248
+ let candidate = 2;
1249
+ while (true) {
1250
+ let prime = true;
1251
+ for (let divisor = 2; divisor * divisor <= candidate; divisor++) {
1252
+ if (candidate % divisor === 0) {
1253
+ prime = false;
1254
+ break;
1255
+ }
1256
+ }
1257
+ if (prime && primeCount++ === index) {
1258
+ return Math.floor(Math.cbrt(candidate) % 1 * 2 ** 32) >>> 0;
1259
+ }
1260
+ candidate++;
1261
+ }
1262
+ });
1263
+ const rotateRight = (value, amount) => value >>> amount | value << 32 - amount;
1264
+ for (let offset = 0; offset < words.length; offset += 64) {
1265
+ const schedule = new Array(64);
1266
+ for (let i = 0; i < 16; i++) {
1267
+ const base = offset + i * 4;
1268
+ schedule[i] = (words[base] << 24 | words[base + 1] << 16 | words[base + 2] << 8 | words[base + 3]) >>> 0;
1269
+ }
1270
+ for (let i = 16; i < 64; i++) {
1271
+ const s0 = rotateRight(schedule[i - 15], 7) ^ rotateRight(schedule[i - 15], 18) ^ schedule[i - 15] >>> 3;
1272
+ const s1 = rotateRight(schedule[i - 2], 17) ^ rotateRight(schedule[i - 2], 19) ^ schedule[i - 2] >>> 10;
1273
+ schedule[i] = schedule[i - 16] + s0 + schedule[i - 7] + s1 >>> 0;
1274
+ }
1275
+ let [a, b, c, d, e, f, g, hh] = h;
1276
+ for (let i = 0; i < 64; i++) {
1277
+ const s1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25);
1278
+ const choice = e & f ^ ~e & g;
1279
+ const temp1 = hh + s1 + choice + k[i] + schedule[i] >>> 0;
1280
+ const s0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22);
1281
+ const majority = a & b ^ a & c ^ b & c;
1282
+ const temp2 = s0 + majority >>> 0;
1283
+ hh = g;
1284
+ g = f;
1285
+ f = e;
1286
+ e = d + temp1 >>> 0;
1287
+ d = c;
1288
+ c = b;
1289
+ b = a;
1290
+ a = temp1 + temp2 >>> 0;
1291
+ }
1292
+ [a, b, c, d, e, f, g, hh].forEach((value, index) => {
1293
+ h[index] = h[index] + value >>> 0;
1294
+ });
1295
+ }
1296
+ return h.map((value) => value.toString(16).padStart(8, "0")).join("");
1297
+ }
1298
+ function encodeKeyPart(value, keepSlash = false) {
1299
+ let encoded = encodeURIComponent(value).replace(
1300
+ /[!'()*]/g,
1301
+ (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`
1302
+ );
1303
+ encoded = encoded.replace(/%40/gi, "@");
1304
+ if (keepSlash) encoded = encoded.replace(/%2F/gi, "/").replace(/%5C/gi, "\\");
1305
+ return encoded;
1306
+ }
968
1307
  function hashString(content, length = 16) {
969
1308
  let hash = 0;
970
1309
  for (let i = 0; i < content.length; i++) {
@@ -974,14 +1313,35 @@ function hashString(content, length = 16) {
974
1313
  const hex = Math.abs(hash).toString(16).padStart(8, "0");
975
1314
  return hex.slice(0, length);
976
1315
  }
977
- function generateObservableKey(obsType, value) {
1316
+ function generateObservableKey(obsType, value, subtype, namespace) {
978
1317
  const normalizedType = normalizeValue(obsType);
979
- const normalizedValue = normalizeValue(value);
980
- return `obs:${normalizedType}:${normalizedValue}`;
1318
+ const normalizedSubtype = subtype ? normalizeValue(subtype) : void 0;
1319
+ const normalizedNamespace = namespace?.trim().toLowerCase() || void 0;
1320
+ const normalizedValue = normalizeObservableValue(
1321
+ normalizedType,
1322
+ value,
1323
+ normalizedSubtype
1324
+ );
1325
+ const identity = JSON.stringify({
1326
+ namespace: normalizedNamespace ?? null,
1327
+ subtype: normalizedSubtype ?? null,
1328
+ type: normalizedType,
1329
+ value: normalizedValue
1330
+ });
1331
+ if (normalizedType === "command_line" || new TextEncoder().encode(identity).length > 128) {
1332
+ return `obs:${normalizedType}:sha256:${sha256(identity)}`;
1333
+ }
1334
+ if (!normalizedSubtype && !normalizedNamespace) {
1335
+ return `obs:${normalizedType}:${normalizedValue.toLowerCase()}`;
1336
+ }
1337
+ const parts = ["obs", encodeKeyPart(normalizedType), normalizedSubtype ? encodeKeyPart(normalizedSubtype) : "_"];
1338
+ if (normalizedNamespace) parts.push(encodeKeyPart(normalizedNamespace));
1339
+ parts.push(encodeKeyPart(normalizedValue, true));
1340
+ return parts.join(":");
981
1341
  }
982
- function generateCheckKey(checkName) {
983
- const normalizedName = normalizeValue(checkName);
984
- return `chk:${normalizedName}`;
1342
+ function generateFindingKey(findingName) {
1343
+ const normalizedName = normalizeValue(findingName);
1344
+ return `fnd:${normalizedName}`;
985
1345
  }
986
1346
  function generateThreatIntelKey(source, observableKey) {
987
1347
  const normalizedSource = normalizeValue(source);
@@ -1020,7 +1380,7 @@ function isTagDescendantOf(descendantName, ancestorName) {
1020
1380
  function parseKeyType(key) {
1021
1381
  if (key.includes(":")) {
1022
1382
  const prefix = key.split(":", 1)[0];
1023
- if (["obs", "chk", "ti", "enr", "tag"].includes(prefix)) {
1383
+ if (["obs", "fnd", "evd", "ti", "enr", "tag"].includes(prefix)) {
1024
1384
  return prefix;
1025
1385
  }
1026
1386
  }
@@ -1053,14 +1413,14 @@ function parseObservableKey(key) {
1053
1413
  }
1054
1414
  return null;
1055
1415
  }
1056
- function parseCheckKey(key) {
1057
- if (!validateKey(key, "chk")) {
1416
+ function parseFindingKey(key) {
1417
+ if (!validateKey(key, "fnd")) {
1058
1418
  return null;
1059
1419
  }
1060
1420
  const parts = key.split(":");
1061
1421
  if (parts.length >= 2) {
1062
1422
  return {
1063
- checkName: parts.slice(1).join(":")
1423
+ findingName: parts.slice(1).join(":")
1064
1424
  };
1065
1425
  }
1066
1426
  return null;
@@ -1193,15 +1553,8 @@ function getEntityLevel(entity) {
1193
1553
  function getObservable(inv, key) {
1194
1554
  return inv.observables[key];
1195
1555
  }
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;
1556
+ function getObservableByTypeValue(inv, type, value, subtype, namespace) {
1557
+ return inv.observables[generateObservableKey(type, value, subtype, namespace)];
1205
1558
  }
1206
1559
  function getRootObservable(inv) {
1207
1560
  const rootType = inv.data_extraction.root_type;
@@ -1211,15 +1564,21 @@ function getRootObservable(inv) {
1211
1564
  const rootKey = generateObservableKey(rootType, "root");
1212
1565
  return inv.observables[rootKey];
1213
1566
  }
1214
- function getCheck(inv, key) {
1215
- return inv.checks[key];
1567
+ function getFinding(inv, key) {
1568
+ return inv.findings[key];
1569
+ }
1570
+ function getFindingByName(inv, findingName) {
1571
+ const key = generateFindingKey(findingName);
1572
+ return inv.findings[key];
1573
+ }
1574
+ function getAllFindings(inv) {
1575
+ return Object.values(inv.findings);
1216
1576
  }
1217
- function getCheckByName(inv, checkName) {
1218
- const key = generateCheckKey(checkName);
1219
- return inv.checks[key];
1577
+ function getEvidence(inv, key) {
1578
+ return inv.evidences[key];
1220
1579
  }
1221
- function getAllChecks(inv) {
1222
- return Object.values(inv.checks);
1580
+ function getAllEvidences(inv) {
1581
+ return Object.values(inv.evidences);
1223
1582
  }
1224
1583
  function getThreatIntel(inv, key) {
1225
1584
  return inv.threat_intels[key];
@@ -1276,7 +1635,8 @@ function getDataExtraction(inv) {
1276
1635
  function getCounts(inv) {
1277
1636
  return {
1278
1637
  observables: Object.keys(inv.observables).length,
1279
- checks: getAllChecks(inv).length,
1638
+ findings: getAllFindings(inv).length,
1639
+ evidences: getAllEvidences(inv).length,
1280
1640
  threatIntels: Object.keys(inv.threat_intels).length,
1281
1641
  enrichments: Object.keys(inv.enrichments).length,
1282
1642
  tags: getAllTags(inv).length,
@@ -1358,18 +1718,18 @@ function findObservablesWithThreatIntel(inv) {
1358
1718
  (obs) => obs.threat_intels.length > 0
1359
1719
  );
1360
1720
  }
1361
- function findChecksByLevel(inv, level) {
1362
- return Object.values(inv.checks).filter((check) => check.level === level);
1721
+ function findFindingsByLevel(inv, level) {
1722
+ return Object.values(inv.findings).filter((finding) => finding.level === level);
1363
1723
  }
1364
- function findChecksAtLeast(inv, minLevel2) {
1365
- return Object.values(inv.checks).filter(
1366
- (check) => isLevelAtLeast(check.level, minLevel2)
1724
+ function findFindingsAtLeast(inv, minLevel2) {
1725
+ return Object.values(inv.findings).filter(
1726
+ (finding) => isLevelAtLeast(finding.level, minLevel2)
1367
1727
  );
1368
1728
  }
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
1729
+ function findFindingByName(inv, findingName) {
1730
+ const normalizedName = findingName.trim().toLowerCase();
1731
+ return Object.values(inv.findings).find(
1732
+ (finding) => finding.finding_name.toLowerCase() === normalizedName
1373
1733
  );
1374
1734
  }
1375
1735
  function findThreatIntelBySource(inv, source) {
@@ -1397,26 +1757,26 @@ function findTagsAtLeast(inv, minLevel2) {
1397
1757
  function findTagsByNamePattern(inv, pattern) {
1398
1758
  return Object.values(inv.tags).filter((tag) => pattern.test(tag.name));
1399
1759
  }
1400
- function findChecksForObservable(inv, observableKey) {
1760
+ function findFindingsForObservable(inv, observableKey) {
1401
1761
  const result = [];
1402
1762
  const seen = /* @__PURE__ */ new Set();
1403
1763
  const observable = inv.observables[observableKey];
1404
1764
  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);
1765
+ for (const findingKey of observable.finding_links) {
1766
+ const finding = inv.findings[findingKey];
1767
+ if (finding && !seen.has(finding.key)) {
1768
+ result.push(finding);
1769
+ seen.add(finding.key);
1410
1770
  }
1411
1771
  }
1412
1772
  }
1413
- for (const check of Object.values(inv.checks)) {
1414
- if (seen.has(check.key)) {
1773
+ for (const finding of Object.values(inv.findings)) {
1774
+ if (seen.has(finding.key)) {
1415
1775
  continue;
1416
1776
  }
1417
- if (check.observable_links.some((link) => link.observable_key === observableKey)) {
1418
- result.push(check);
1419
- seen.add(check.key);
1777
+ if (finding.observable_links.some((link) => link.observable_key === observableKey)) {
1778
+ result.push(finding);
1779
+ seen.add(finding.key);
1420
1780
  }
1421
1781
  }
1422
1782
  return result;
@@ -1430,37 +1790,37 @@ function findThreatIntelsForObservable(inv, observableKey) {
1430
1790
  (ti) => ti.observable_key === observableKey
1431
1791
  );
1432
1792
  }
1433
- function findObservablesForCheck(inv, checkKey) {
1434
- const check = inv.checks[checkKey];
1435
- if (check) {
1793
+ function findObservablesForFinding(inv, findingKey) {
1794
+ const finding = inv.findings[findingKey];
1795
+ if (finding) {
1436
1796
  const keys = /* @__PURE__ */ new Set();
1437
- for (const link of check.observable_links) {
1797
+ for (const link of finding.observable_links) {
1438
1798
  keys.add(link.observable_key);
1439
1799
  }
1440
1800
  return Array.from(keys).map((obsKey) => inv.observables[obsKey]).filter((obs) => obs !== void 0);
1441
1801
  }
1442
1802
  return [];
1443
1803
  }
1444
- function findChecksForTag(inv, tagKey, recursive = false) {
1804
+ function findFindingsForTag(inv, tagKey, recursive = false) {
1445
1805
  const result = [];
1446
1806
  const tag = inv.tags[tagKey];
1447
1807
  if (!tag) {
1448
1808
  return result;
1449
1809
  }
1450
- for (const checkKey of tag.checks) {
1451
- const check = inv.checks[checkKey];
1452
- if (check) {
1453
- result.push(check);
1810
+ for (const findingKey of tag.findings) {
1811
+ const finding = inv.findings[findingKey];
1812
+ if (finding) {
1813
+ result.push(finding);
1454
1814
  }
1455
1815
  }
1456
1816
  if (recursive) {
1457
1817
  const prefix = tag.name + ":";
1458
1818
  for (const otherTag of Object.values(inv.tags)) {
1459
1819
  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);
1820
+ for (const findingKey of otherTag.findings) {
1821
+ const finding = inv.findings[findingKey];
1822
+ if (finding) {
1823
+ result.push(finding);
1464
1824
  }
1465
1825
  }
1466
1826
  }
@@ -1471,24 +1831,24 @@ function findChecksForTag(inv, tagKey, recursive = false) {
1471
1831
  function sortObservablesByScore(observables) {
1472
1832
  return [...observables].sort((a, b) => b.score - a.score);
1473
1833
  }
1474
- function sortChecksByScore(checks) {
1475
- return [...checks].sort((a, b) => b.score - a.score);
1834
+ function sortFindingsByScore(findings) {
1835
+ return [...findings].sort((a, b) => b.score - a.score);
1476
1836
  }
1477
1837
  function sortObservablesByLevel(observables) {
1478
1838
  return [...observables].sort(
1479
1839
  (a, b) => LEVEL_VALUES[b.level] - LEVEL_VALUES[a.level]
1480
1840
  );
1481
1841
  }
1482
- function sortChecksByLevel(checks) {
1483
- return [...checks].sort(
1842
+ function sortFindingsByLevel(findings) {
1843
+ return [...findings].sort(
1484
1844
  (a, b) => LEVEL_VALUES[b.level] - LEVEL_VALUES[a.level]
1485
1845
  );
1486
1846
  }
1487
1847
  function findHighestScoringObservables(inv, n = 10) {
1488
1848
  return sortObservablesByScore(Object.values(inv.observables)).slice(0, n);
1489
1849
  }
1490
- function findHighestScoringChecks(inv, n = 10) {
1491
- return sortChecksByScore(Object.values(inv.checks)).slice(0, n);
1850
+ function findHighestScoringFindings(inv, n = 10) {
1851
+ return sortFindingsByScore(Object.values(inv.findings)).slice(0, n);
1492
1852
  }
1493
1853
  function findMaliciousObservables(inv) {
1494
1854
  return findObservablesByLevel(inv, "MALICIOUS");
@@ -1496,14 +1856,14 @@ function findMaliciousObservables(inv) {
1496
1856
  function findSuspiciousObservables(inv) {
1497
1857
  return findObservablesByLevel(inv, "SUSPICIOUS");
1498
1858
  }
1499
- function findMaliciousChecks(inv) {
1500
- return findChecksByLevel(inv, "MALICIOUS");
1859
+ function findMaliciousFindings(inv) {
1860
+ return findFindingsByLevel(inv, "MALICIOUS");
1501
1861
  }
1502
- function findSuspiciousChecks(inv) {
1503
- return findChecksByLevel(inv, "SUSPICIOUS");
1862
+ function findSuspiciousFindings(inv) {
1863
+ return findFindingsByLevel(inv, "SUSPICIOUS");
1504
1864
  }
1505
- function getAllCheckKeys(inv) {
1506
- return Object.keys(inv.checks);
1865
+ function getAllFindingKeys(inv) {
1866
+ return Object.keys(inv.findings);
1507
1867
  }
1508
1868
  function getAllObservableTypes(inv) {
1509
1869
  const types = /* @__PURE__ */ new Set();
@@ -1788,30 +2148,30 @@ function getRelationshipsForObservable(inv, observableKey) {
1788
2148
  areConnected,
1789
2149
  compareLevels,
1790
2150
  countRelationshipsByType,
1791
- findCheckByName,
1792
- findChecksAtLeast,
1793
- findChecksByLevel,
1794
- findChecksForObservable,
1795
- findChecksForTag,
1796
2151
  findExternalObservables,
1797
- findHighestScoringChecks,
2152
+ findFindingByName,
2153
+ findFindingsAtLeast,
2154
+ findFindingsByLevel,
2155
+ findFindingsForObservable,
2156
+ findFindingsForTag,
2157
+ findHighestScoringFindings,
1798
2158
  findHighestScoringObservables,
1799
2159
  findInternalObservables,
1800
2160
  findLeafObservables,
1801
- findMaliciousChecks,
2161
+ findMaliciousFindings,
1802
2162
  findMaliciousObservables,
1803
2163
  findObservablesAtLeast,
1804
2164
  findObservablesByLevel,
1805
2165
  findObservablesByType,
1806
2166
  findObservablesByValue,
1807
2167
  findObservablesContaining,
1808
- findObservablesForCheck,
2168
+ findObservablesForFinding,
1809
2169
  findObservablesMatching,
1810
2170
  findObservablesWithThreatIntel,
1811
2171
  findOrphanObservables,
1812
2172
  findPath,
1813
2173
  findSourceObservables,
1814
- findSuspiciousChecks,
2174
+ findSuspiciousFindings,
1815
2175
  findSuspiciousObservables,
1816
2176
  findTagsAtLeast,
1817
2177
  findTagsByLevel,
@@ -1821,22 +2181,21 @@ function getRelationshipsForObservable(inv, observableKey) {
1821
2181
  findThreatIntelBySource,
1822
2182
  findThreatIntelsForObservable,
1823
2183
  findWhitelistedObservables,
1824
- generateCheckKey,
1825
2184
  generateEnrichmentKey,
2185
+ generateFindingKey,
1826
2186
  generateObservableKey,
1827
2187
  generateTagKey,
1828
2188
  generateThreatIntelKey,
1829
- getAllCheckKeys,
1830
- getAllChecks,
1831
2189
  getAllEnrichments,
2190
+ getAllEvidences,
2191
+ getAllFindingKeys,
2192
+ getAllFindings,
1832
2193
  getAllObservableTypes,
1833
2194
  getAllObservables,
1834
2195
  getAllRelationshipTypes,
1835
2196
  getAllTags,
1836
2197
  getAllThreatIntelSources,
1837
2198
  getAllThreatIntels,
1838
- getCheck,
1839
- getCheckByName,
1840
2199
  getColorForLevel,
1841
2200
  getColorForScore,
1842
2201
  getCounts,
@@ -1844,6 +2203,9 @@ function getRelationshipsForObservable(inv, observableKey) {
1844
2203
  getEnrichment,
1845
2204
  getEnrichmentByName,
1846
2205
  getEntityLevel,
2206
+ getEvidence,
2207
+ getFinding,
2208
+ getFindingByName,
1847
2209
  getLevelFromScore,
1848
2210
  getObservable,
1849
2211
  getObservableByTypeValue,
@@ -1879,13 +2241,13 @@ function getRelationshipsForObservable(inv, observableKey) {
1879
2241
  maxLevel,
1880
2242
  minLevel,
1881
2243
  normalizeLevel,
1882
- parseCheckKey,
1883
2244
  parseCyvest,
2245
+ parseFindingKey,
1884
2246
  parseKeyType,
1885
2247
  parseObservableKey,
1886
2248
  parseThreatIntelKey,
1887
- sortChecksByLevel,
1888
- sortChecksByScore,
2249
+ sortFindingsByLevel,
2250
+ sortFindingsByScore,
1889
2251
  sortObservablesByLevel,
1890
2252
  sortObservablesByScore,
1891
2253
  validateKey