@cyvest/cyvest-js 4.4.0 → 5.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.js CHANGED
@@ -1,140 +1,6 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
- LEVEL_COLORS: () => LEVEL_COLORS,
34
- LEVEL_ORDER: () => LEVEL_ORDER,
35
- LEVEL_VALUES: () => LEVEL_VALUES,
36
- areConnected: () => areConnected,
37
- compareLevels: () => compareLevels,
38
- countRelationshipsByType: () => countRelationshipsByType,
39
- findChecksAtLeast: () => findChecksAtLeast,
40
- findChecksByCheckId: () => findChecksByCheckId,
41
- findChecksByLevel: () => findChecksByLevel,
42
- findChecksByScope: () => findChecksByScope,
43
- findContainersAtLeast: () => findContainersAtLeast,
44
- findContainersByLevel: () => findContainersByLevel,
45
- findExternalObservables: () => findExternalObservables,
46
- findInternalObservables: () => findInternalObservables,
47
- findLeafObservables: () => findLeafObservables,
48
- findObservablesAtLeast: () => findObservablesAtLeast,
49
- findObservablesByLevel: () => findObservablesByLevel,
50
- findObservablesByType: () => findObservablesByType,
51
- findObservablesByValue: () => findObservablesByValue,
52
- findObservablesContaining: () => findObservablesContaining,
53
- findObservablesMatching: () => findObservablesMatching,
54
- findObservablesWithThreatIntel: () => findObservablesWithThreatIntel,
55
- findOrphanObservables: () => findOrphanObservables,
56
- findPath: () => findPath,
57
- findRootObservables: () => findRootObservables,
58
- findThreatIntelAtLeast: () => findThreatIntelAtLeast,
59
- findThreatIntelByLevel: () => findThreatIntelByLevel,
60
- findThreatIntelBySource: () => findThreatIntelBySource,
61
- findWhitelistedObservables: () => findWhitelistedObservables,
62
- generateCheckKey: () => generateCheckKey,
63
- generateContainerKey: () => generateContainerKey,
64
- generateEnrichmentKey: () => generateEnrichmentKey,
65
- generateObservableKey: () => generateObservableKey,
66
- generateThreatIntelKey: () => generateThreatIntelKey,
67
- getAllChecks: () => getAllChecks,
68
- getAllContainers: () => getAllContainers,
69
- getAllEnrichments: () => getAllEnrichments,
70
- getAllObservableTypes: () => getAllObservableTypes,
71
- getAllObservables: () => getAllObservables,
72
- getAllRelationshipTypes: () => getAllRelationshipTypes,
73
- getAllScopes: () => getAllScopes,
74
- getAllThreatIntelSources: () => getAllThreatIntelSources,
75
- getAllThreatIntels: () => getAllThreatIntels,
76
- getCheck: () => getCheck,
77
- getCheckByIdScope: () => getCheckByIdScope,
78
- getChecksForContainer: () => getChecksForContainer,
79
- getChecksForObservable: () => getChecksForObservable,
80
- getColorForLevel: () => getColorForLevel,
81
- getColorForScore: () => getColorForScore,
82
- getContainer: () => getContainer,
83
- getContainerByPath: () => getContainerByPath,
84
- getCounts: () => getCounts,
85
- getDataExtraction: () => getDataExtraction,
86
- getEnrichment: () => getEnrichment,
87
- getEnrichmentByName: () => getEnrichmentByName,
88
- getEntityLevel: () => getEntityLevel,
89
- getHighestScoringChecks: () => getHighestScoringChecks,
90
- getHighestScoringObservables: () => getHighestScoringObservables,
91
- getLevelFromScore: () => getLevelFromScore,
92
- getMaliciousChecks: () => getMaliciousChecks,
93
- getMaliciousObservables: () => getMaliciousObservables,
94
- getObservable: () => getObservable,
95
- getObservableByTypeValue: () => getObservableByTypeValue,
96
- getObservableChildren: () => getObservableChildren,
97
- getObservableGraph: () => getObservableGraph,
98
- getObservableParents: () => getObservableParents,
99
- getObservablesForCheck: () => getObservablesForCheck,
100
- getReachableObservables: () => getReachableObservables,
101
- getRelatedObservables: () => getRelatedObservables,
102
- getRelatedObservablesByDirection: () => getRelatedObservablesByDirection,
103
- getRelatedObservablesByType: () => getRelatedObservablesByType,
104
- getRelationshipsForObservable: () => getRelationshipsForObservable,
105
- getStartedAt: () => getStartedAt,
106
- getStats: () => getStats,
107
- getSuspiciousChecks: () => getSuspiciousChecks,
108
- getSuspiciousObservables: () => getSuspiciousObservables,
109
- getThreatIntel: () => getThreatIntel,
110
- getThreatIntelBySourceObservable: () => getThreatIntelBySourceObservable,
111
- getThreatIntelsForObservable: () => getThreatIntelsForObservable,
112
- getWhitelists: () => getWhitelists,
113
- hasLevel: () => hasLevel,
114
- isCyvest: () => isCyvest,
115
- isLevelAtLeast: () => isLevelAtLeast,
116
- isLevelHigherThan: () => isLevelHigherThan,
117
- isLevelLowerThan: () => isLevelLowerThan,
118
- isValidLevel: () => isValidLevel,
119
- maxLevel: () => maxLevel,
120
- minLevel: () => minLevel,
121
- normalizeLevel: () => normalizeLevel,
122
- parseCheckKey: () => parseCheckKey,
123
- parseCyvest: () => parseCyvest,
124
- parseKeyType: () => parseKeyType,
125
- parseObservableKey: () => parseObservableKey,
126
- parseThreatIntelKey: () => parseThreatIntelKey,
127
- sortChecksByLevel: () => sortChecksByLevel,
128
- sortChecksByScore: () => sortChecksByScore,
129
- sortObservablesByLevel: () => sortObservablesByLevel,
130
- sortObservablesByScore: () => sortObservablesByScore,
131
- validateKey: () => validateKey
132
- });
133
- module.exports = __toCommonJS(index_exports);
134
-
135
1
  // src/helpers.ts
136
- var import__ = __toESM(require("ajv/dist/2020"));
137
- var import_ajv_formats = __toESM(require("ajv-formats"));
2
+ import Ajv2020 from "ajv/dist/2020";
3
+ import addFormats from "ajv-formats";
138
4
 
139
5
  // ../../../schema/cyvest.schema.json
140
6
  var cyvest_schema_default = {
@@ -233,12 +99,8 @@ var cyvest_schema_default = {
233
99
  Check: {
234
100
  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.",
235
101
  properties: {
236
- check_id: {
237
- title: "Check Id",
238
- type: "string"
239
- },
240
- scope: {
241
- title: "Scope",
102
+ check_name: {
103
+ title: "Check Name",
242
104
  type: "string"
243
105
  },
244
106
  description: {
@@ -283,8 +145,7 @@ var cyvest_schema_default = {
283
145
  }
284
146
  },
285
147
  required: [
286
- "check_id",
287
- "scope",
148
+ "check_name",
288
149
  "description",
289
150
  "comment",
290
151
  "extra",
@@ -298,59 +159,6 @@ var cyvest_schema_default = {
298
159
  title: "Check",
299
160
  type: "object"
300
161
  },
301
- Container: {
302
- additionalProperties: false,
303
- description: "Groups checks and sub-containers for hierarchical organization.\n\nContainers allow structuring the investigation into logical sections\nwith aggregated scores and levels.",
304
- properties: {
305
- path: {
306
- title: "Path",
307
- type: "string"
308
- },
309
- description: {
310
- default: "",
311
- title: "Description",
312
- type: "string"
313
- },
314
- checks: {
315
- items: {
316
- type: "string"
317
- },
318
- title: "Checks",
319
- type: "array"
320
- },
321
- sub_containers: {
322
- additionalProperties: {
323
- $ref: "#/$defs/Container"
324
- },
325
- title: "Sub Containers",
326
- type: "object"
327
- },
328
- key: {
329
- title: "Key",
330
- type: "string"
331
- },
332
- aggregated_score: {
333
- readOnly: true,
334
- title: "Aggregated Score",
335
- type: "number"
336
- },
337
- aggregated_level: {
338
- $ref: "#/$defs/Level",
339
- description: "Calculate the aggregated level from the aggregated score.\n\nReturns:\n Level based on aggregated score",
340
- readOnly: true
341
- }
342
- },
343
- required: [
344
- "path",
345
- "checks",
346
- "sub_containers",
347
- "key",
348
- "aggregated_score",
349
- "aggregated_level"
350
- ],
351
- title: "Container",
352
- type: "object"
353
- },
354
162
  DataExtractionSchema: {
355
163
  additionalProperties: false,
356
164
  description: "Schema for data extraction metadata.",
@@ -675,16 +483,6 @@ var cyvest_schema_default = {
675
483
  title: "Applied Checks",
676
484
  type: "integer"
677
485
  },
678
- checks_by_scope: {
679
- additionalProperties: {
680
- items: {
681
- type: "string"
682
- },
683
- type: "array"
684
- },
685
- title: "Checks By Scope",
686
- type: "object"
687
- },
688
486
  checks_by_level: {
689
487
  additionalProperties: {
690
488
  items: {
@@ -716,9 +514,9 @@ var cyvest_schema_default = {
716
514
  title: "Threat Intel By Level",
717
515
  type: "object"
718
516
  },
719
- total_containers: {
517
+ total_tags: {
720
518
  minimum: 0,
721
- title: "Total Containers",
519
+ title: "Total Tags",
722
520
  type: "integer"
723
521
  }
724
522
  },
@@ -730,11 +528,57 @@ var cyvest_schema_default = {
730
528
  "total_checks",
731
529
  "applied_checks",
732
530
  "total_threat_intel",
733
- "total_containers"
531
+ "total_tags"
734
532
  ],
735
533
  title: "StatisticsSchema",
736
534
  type: "object"
737
535
  },
536
+ Tag: {
537
+ additionalProperties: false,
538
+ 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").',
539
+ properties: {
540
+ name: {
541
+ title: "Name",
542
+ type: "string"
543
+ },
544
+ description: {
545
+ default: "",
546
+ title: "Description",
547
+ type: "string"
548
+ },
549
+ checks: {
550
+ items: {
551
+ type: "string"
552
+ },
553
+ title: "Checks",
554
+ type: "array"
555
+ },
556
+ key: {
557
+ title: "Key",
558
+ type: "string"
559
+ },
560
+ direct_score: {
561
+ 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",
562
+ readOnly: true,
563
+ title: "Direct Score",
564
+ type: "number"
565
+ },
566
+ direct_level: {
567
+ $ref: "#/$defs/Level",
568
+ 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",
569
+ readOnly: true
570
+ }
571
+ },
572
+ required: [
573
+ "name",
574
+ "checks",
575
+ "key",
576
+ "direct_score",
577
+ "direct_level"
578
+ ],
579
+ title: "Tag",
580
+ type: "object"
581
+ },
738
582
  Taxonomy: {
739
583
  additionalProperties: false,
740
584
  description: "Represents a structured taxonomy entry for threat intelligence.",
@@ -888,12 +732,9 @@ var cyvest_schema_default = {
888
732
  },
889
733
  checks: {
890
734
  additionalProperties: {
891
- items: {
892
- $ref: "#/$defs/Check"
893
- },
894
- type: "array"
735
+ $ref: "#/$defs/Check"
895
736
  },
896
- description: "Checks organized by scope.",
737
+ description: "Checks keyed by their unique key.",
897
738
  title: "Checks",
898
739
  type: "object"
899
740
  },
@@ -913,12 +754,12 @@ var cyvest_schema_default = {
913
754
  title: "Enrichments",
914
755
  type: "object"
915
756
  },
916
- containers: {
757
+ tags: {
917
758
  additionalProperties: {
918
- $ref: "#/$defs/Container"
759
+ $ref: "#/$defs/Tag"
919
760
  },
920
- description: "Containers keyed by their unique key.",
921
- title: "Containers",
761
+ description: "Tags keyed by their unique key.",
762
+ title: "Tags",
922
763
  type: "object"
923
764
  },
924
765
  stats: {
@@ -946,7 +787,7 @@ var cyvest_schema_default = {
946
787
  "checks",
947
788
  "threat_intels",
948
789
  "enrichments",
949
- "containers",
790
+ "tags",
950
791
  "stats",
951
792
  "data_extraction",
952
793
  "score_display"
@@ -956,8 +797,8 @@ var cyvest_schema_default = {
956
797
  };
957
798
 
958
799
  // src/helpers.ts
959
- var ajv = new import__.default({ allErrors: true });
960
- (0, import_ajv_formats.default)(ajv);
800
+ var ajv = new Ajv2020({ allErrors: true });
801
+ addFormats(ajv);
961
802
  var validateFn = null;
962
803
  function getValidator() {
963
804
  if (!validateFn) {
@@ -996,10 +837,9 @@ function generateObservableKey(obsType, value) {
996
837
  const normalizedValue = normalizeValue(value);
997
838
  return `obs:${normalizedType}:${normalizedValue}`;
998
839
  }
999
- function generateCheckKey(checkId, scope) {
1000
- const normalizedId = normalizeValue(checkId);
1001
- const normalizedScope = normalizeValue(scope);
1002
- return `chk:${normalizedId}:${normalizedScope}`;
840
+ function generateCheckKey(checkName) {
841
+ const normalizedName = normalizeValue(checkName);
842
+ return `chk:${normalizedName}`;
1003
843
  }
1004
844
  function generateThreatIntelKey(source, observableKey) {
1005
845
  const normalizedSource = normalizeValue(source);
@@ -1013,15 +853,32 @@ function generateEnrichmentKey(name, context) {
1013
853
  }
1014
854
  return `enr:${normalizedName}`;
1015
855
  }
1016
- function generateContainerKey(path) {
1017
- let normalizedPath = path.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
1018
- normalizedPath = normalizeValue(normalizedPath);
1019
- return `ctr:${normalizedPath}`;
856
+ function generateTagKey(name) {
857
+ const normalizedName = normalizeValue(name);
858
+ return `tag:${normalizedName}`;
859
+ }
860
+ function getTagAncestors(name) {
861
+ const parts = name.split(":");
862
+ const ancestors = [];
863
+ for (let i = 0; i < parts.length - 1; i++) {
864
+ ancestors.push(parts.slice(0, i + 1).join(":"));
865
+ }
866
+ return ancestors;
867
+ }
868
+ function isTagChildOf(childName, parentName) {
869
+ if (!childName.startsWith(parentName + ":")) {
870
+ return false;
871
+ }
872
+ const remaining = childName.slice(parentName.length + 1);
873
+ return !remaining.includes(":");
874
+ }
875
+ function isTagDescendantOf(descendantName, ancestorName) {
876
+ return descendantName.startsWith(ancestorName + ":");
1020
877
  }
1021
878
  function parseKeyType(key) {
1022
879
  if (key.includes(":")) {
1023
880
  const prefix = key.split(":", 1)[0];
1024
- if (["obs", "chk", "ti", "enr", "ctr"].includes(prefix)) {
881
+ if (["obs", "chk", "ti", "enr", "tag"].includes(prefix)) {
1025
882
  return prefix;
1026
883
  }
1027
884
  }
@@ -1059,10 +916,9 @@ function parseCheckKey(key) {
1059
916
  return null;
1060
917
  }
1061
918
  const parts = key.split(":");
1062
- if (parts.length >= 3) {
919
+ if (parts.length >= 2) {
1063
920
  return {
1064
- checkId: parts[1],
1065
- scope: parts.slice(2).join(":")
921
+ checkName: parts.slice(1).join(":")
1066
922
  };
1067
923
  }
1068
924
  return null;
@@ -1179,10 +1035,10 @@ function hasLevel(obj) {
1179
1035
  return typeof obj === "object" && obj !== null && "level" in obj && typeof obj.level === "string" && isValidLevel(obj.level);
1180
1036
  }
1181
1037
  function getEntityLevel(entity) {
1182
- if ("aggregated_level" in entity) {
1183
- const aggregatedLevel = entity.aggregated_level;
1184
- if (typeof aggregatedLevel === "string" && isValidLevel(aggregatedLevel)) {
1185
- return aggregatedLevel;
1038
+ if ("direct_level" in entity) {
1039
+ const directLevel = entity.direct_level;
1040
+ if (typeof directLevel === "string" && isValidLevel(directLevel)) {
1041
+ return directLevel;
1186
1042
  }
1187
1043
  }
1188
1044
  if ("level" in entity && isValidLevel(entity.level)) {
@@ -1205,40 +1061,24 @@ function getObservableByTypeValue(inv, type, value) {
1205
1061
  }
1206
1062
  return void 0;
1207
1063
  }
1208
- function getCheck(inv, key) {
1209
- for (const checks of Object.values(inv.checks)) {
1210
- for (const check of checks) {
1211
- if (check.key === key) {
1212
- return check;
1213
- }
1214
- }
1064
+ function getRootObservable(inv) {
1065
+ const rootType = inv.data_extraction.root_type;
1066
+ if (!rootType) {
1067
+ return void 0;
1215
1068
  }
1216
- return void 0;
1069
+ const rootKey = generateObservableKey(rootType, "root");
1070
+ return inv.observables[rootKey];
1217
1071
  }
1218
- function getCheckByIdScope(inv, checkId, scope) {
1219
- const normalizedId = checkId.trim().toLowerCase();
1220
- const normalizedScope = scope.trim().toLowerCase();
1221
- const scopeChecks = inv.checks[normalizedScope] || inv.checks[scope];
1222
- if (scopeChecks) {
1223
- return scopeChecks.find(
1224
- (c) => c.check_id.toLowerCase() === normalizedId
1225
- );
1226
- }
1227
- for (const checks of Object.values(inv.checks)) {
1228
- for (const check of checks) {
1229
- if (check.check_id.toLowerCase() === normalizedId && check.scope.toLowerCase() === normalizedScope) {
1230
- return check;
1231
- }
1232
- }
1233
- }
1234
- return void 0;
1072
+ function getCheck(inv, key) {
1073
+ return inv.checks[key];
1074
+ }
1075
+ function getCheckByName(inv, checkName) {
1076
+ const normalizedName = checkName.trim().toLowerCase();
1077
+ const key = `chk:${normalizedName}`;
1078
+ return inv.checks[key];
1235
1079
  }
1236
1080
  function getAllChecks(inv) {
1237
- const result = [];
1238
- for (const checks of Object.values(inv.checks)) {
1239
- result.push(...checks);
1240
- }
1241
- return result;
1081
+ return Object.values(inv.checks);
1242
1082
  }
1243
1083
  function getThreatIntel(inv, key) {
1244
1084
  return inv.threat_intels[key];
@@ -1270,46 +1110,16 @@ function getEnrichmentByName(inv, name) {
1270
1110
  function getAllEnrichments(inv) {
1271
1111
  return Object.values(inv.enrichments);
1272
1112
  }
1273
- function getContainer(inv, key) {
1274
- if (inv.containers[key]) {
1275
- return inv.containers[key];
1276
- }
1277
- function searchSubContainers(containers) {
1278
- for (const container of Object.values(containers)) {
1279
- if (container.key === key) {
1280
- return container;
1281
- }
1282
- const found = searchSubContainers(container.sub_containers);
1283
- if (found) return found;
1284
- }
1285
- return void 0;
1286
- }
1287
- return searchSubContainers(inv.containers);
1288
- }
1289
- function getContainerByPath(inv, path) {
1290
- const normalizedPath = path.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "").toLowerCase();
1291
- function searchContainers(containers) {
1292
- for (const container of Object.values(containers)) {
1293
- if (container.path.toLowerCase() === normalizedPath) {
1294
- return container;
1295
- }
1296
- const found = searchContainers(container.sub_containers);
1297
- if (found) return found;
1298
- }
1299
- return void 0;
1300
- }
1301
- return searchContainers(inv.containers);
1113
+ function getTag(inv, key) {
1114
+ return inv.tags[key];
1302
1115
  }
1303
- function getAllContainers(inv) {
1304
- const result = [];
1305
- function collectContainers(containers) {
1306
- for (const container of Object.values(containers)) {
1307
- result.push(container);
1308
- collectContainers(container.sub_containers);
1309
- }
1310
- }
1311
- collectContainers(inv.containers);
1312
- return result;
1116
+ function getTagByName(inv, name) {
1117
+ const normalizedName = name.trim().toLowerCase();
1118
+ const key = `tag:${normalizedName}`;
1119
+ return inv.tags[key];
1120
+ }
1121
+ function getAllTags(inv) {
1122
+ return Object.values(inv.tags);
1313
1123
  }
1314
1124
  function getAllObservables(inv) {
1315
1125
  return Object.values(inv.observables);
@@ -1329,7 +1139,7 @@ function getCounts(inv) {
1329
1139
  checks: getAllChecks(inv).length,
1330
1140
  threatIntels: Object.keys(inv.threat_intels).length,
1331
1141
  enrichments: Object.keys(inv.enrichments).length,
1332
- containers: getAllContainers(inv).length,
1142
+ tags: getAllTags(inv).length,
1333
1143
  whitelists: inv.whitelists.length
1334
1144
  };
1335
1145
  }
@@ -1339,6 +1149,28 @@ function getStartedAt(inv) {
1339
1149
  );
1340
1150
  return event?.timestamp;
1341
1151
  }
1152
+ function getTagChildren(inv, tagName) {
1153
+ return Object.values(inv.tags).filter((tag) => isTagChildOf(tag.name, tagName));
1154
+ }
1155
+ function getTagDescendants(inv, tagName) {
1156
+ const prefix = tagName + ":";
1157
+ return Object.values(inv.tags).filter((tag) => tag.name.startsWith(prefix));
1158
+ }
1159
+ function getTagAggregatedScore(inv, tagName) {
1160
+ const tag = getTagByName(inv, tagName);
1161
+ if (!tag) {
1162
+ return 0;
1163
+ }
1164
+ let total = tag.direct_score;
1165
+ const children = getTagChildren(inv, tagName);
1166
+ for (const child of children) {
1167
+ total += getTagAggregatedScore(inv, child.name);
1168
+ }
1169
+ return total;
1170
+ }
1171
+ function getTagAggregatedLevel(inv, tagName) {
1172
+ return getLevelFromScore(getTagAggregatedScore(inv, tagName));
1173
+ }
1342
1174
 
1343
1175
  // src/finders.ts
1344
1176
  function findObservablesByType(inv, type) {
@@ -1386,51 +1218,19 @@ function findObservablesWithThreatIntel(inv) {
1386
1218
  (obs) => obs.threat_intels.length > 0
1387
1219
  );
1388
1220
  }
1389
- function findChecksByScope(inv, scope) {
1390
- const normalizedScope = scope.trim().toLowerCase();
1391
- if (inv.checks[scope]) {
1392
- return inv.checks[scope];
1393
- }
1394
- for (const [key, checks] of Object.entries(inv.checks)) {
1395
- if (key.toLowerCase() === normalizedScope) {
1396
- return checks;
1397
- }
1398
- }
1399
- return [];
1400
- }
1401
1221
  function findChecksByLevel(inv, level) {
1402
- const result = [];
1403
- for (const checks of Object.values(inv.checks)) {
1404
- for (const check of checks) {
1405
- if (check.level === level) {
1406
- result.push(check);
1407
- }
1408
- }
1409
- }
1410
- return result;
1222
+ return Object.values(inv.checks).filter((check) => check.level === level);
1411
1223
  }
1412
1224
  function findChecksAtLeast(inv, minLevel2) {
1413
- const result = [];
1414
- for (const checks of Object.values(inv.checks)) {
1415
- for (const check of checks) {
1416
- if (isLevelAtLeast(check.level, minLevel2)) {
1417
- result.push(check);
1418
- }
1419
- }
1420
- }
1421
- return result;
1225
+ return Object.values(inv.checks).filter(
1226
+ (check) => isLevelAtLeast(check.level, minLevel2)
1227
+ );
1422
1228
  }
1423
- function findChecksByCheckId(inv, checkId) {
1424
- const normalizedId = checkId.trim().toLowerCase();
1425
- const result = [];
1426
- for (const checks of Object.values(inv.checks)) {
1427
- for (const check of checks) {
1428
- if (check.check_id.toLowerCase() === normalizedId) {
1429
- result.push(check);
1430
- }
1431
- }
1432
- }
1433
- return result;
1229
+ function findCheckByName(inv, checkName) {
1230
+ const normalizedName = checkName.trim().toLowerCase();
1231
+ return Object.values(inv.checks).find(
1232
+ (check) => check.check_name.toLowerCase() === normalizedName
1233
+ );
1434
1234
  }
1435
1235
  function findThreatIntelBySource(inv, source) {
1436
1236
  const normalizedSource = source.trim().toLowerCase();
@@ -1446,52 +1246,31 @@ function findThreatIntelAtLeast(inv, minLevel2) {
1446
1246
  (ti) => isLevelAtLeast(ti.level, minLevel2)
1447
1247
  );
1448
1248
  }
1449
- function findContainersByLevel(inv, level) {
1450
- const result = [];
1451
- function searchContainers(containers) {
1452
- for (const container of Object.values(containers)) {
1453
- if (container.aggregated_level === level) {
1454
- result.push(container);
1455
- }
1456
- searchContainers(container.sub_containers);
1457
- }
1458
- }
1459
- searchContainers(inv.containers);
1460
- return result;
1249
+ function findTagsByLevel(inv, level) {
1250
+ return Object.values(inv.tags).filter((tag) => tag.direct_level === level);
1461
1251
  }
1462
- function findContainersAtLeast(inv, minLevel2) {
1463
- const result = [];
1464
- function searchContainers(containers) {
1465
- for (const container of Object.values(containers)) {
1466
- if (isLevelAtLeast(container.aggregated_level, minLevel2)) {
1467
- result.push(container);
1468
- }
1469
- searchContainers(container.sub_containers);
1470
- }
1471
- }
1472
- searchContainers(inv.containers);
1473
- return result;
1252
+ function findTagsAtLeast(inv, minLevel2) {
1253
+ return Object.values(inv.tags).filter(
1254
+ (tag) => isLevelAtLeast(tag.direct_level, minLevel2)
1255
+ );
1256
+ }
1257
+ function findTagsByNamePattern(inv, pattern) {
1258
+ return Object.values(inv.tags).filter((tag) => pattern.test(tag.name));
1474
1259
  }
1475
- function getChecksForObservable(inv, observableKey) {
1260
+ function findChecksForObservable(inv, observableKey) {
1476
1261
  const result = [];
1477
1262
  const seen = /* @__PURE__ */ new Set();
1478
- const checkLookup = /* @__PURE__ */ new Map();
1479
- for (const checks of Object.values(inv.checks)) {
1480
- for (const check of checks) {
1481
- checkLookup.set(check.key, check);
1482
- }
1483
- }
1484
1263
  const observable = inv.observables[observableKey];
1485
1264
  if (observable) {
1486
1265
  for (const checkKey of observable.check_links) {
1487
- const check = checkLookup.get(checkKey);
1266
+ const check = inv.checks[checkKey];
1488
1267
  if (check && !seen.has(check.key)) {
1489
1268
  result.push(check);
1490
1269
  seen.add(check.key);
1491
1270
  }
1492
1271
  }
1493
1272
  }
1494
- for (const check of checkLookup.values()) {
1273
+ for (const check of Object.values(inv.checks)) {
1495
1274
  if (seen.has(check.key)) {
1496
1275
  continue;
1497
1276
  }
@@ -1502,7 +1281,7 @@ function getChecksForObservable(inv, observableKey) {
1502
1281
  }
1503
1282
  return result;
1504
1283
  }
1505
- function getThreatIntelsForObservable(inv, observableKey) {
1284
+ function findThreatIntelsForObservable(inv, observableKey) {
1506
1285
  const observable = inv.observables[observableKey];
1507
1286
  if (observable) {
1508
1287
  return observable.threat_intels.map((tiKey) => inv.threat_intels[tiKey]).filter((ti) => ti !== void 0);
@@ -1511,51 +1290,41 @@ function getThreatIntelsForObservable(inv, observableKey) {
1511
1290
  (ti) => ti.observable_key === observableKey
1512
1291
  );
1513
1292
  }
1514
- function getObservablesForCheck(inv, checkKey) {
1515
- for (const checks of Object.values(inv.checks)) {
1516
- for (const check of checks) {
1517
- if (check.key === checkKey) {
1518
- const keys = /* @__PURE__ */ new Set();
1519
- for (const link of check.observable_links) {
1520
- keys.add(link.observable_key);
1521
- }
1522
- return Array.from(keys).map((obsKey) => inv.observables[obsKey]).filter((obs) => obs !== void 0);
1523
- }
1293
+ function findObservablesForCheck(inv, checkKey) {
1294
+ const check = inv.checks[checkKey];
1295
+ if (check) {
1296
+ const keys = /* @__PURE__ */ new Set();
1297
+ for (const link of check.observable_links) {
1298
+ keys.add(link.observable_key);
1524
1299
  }
1300
+ return Array.from(keys).map((obsKey) => inv.observables[obsKey]).filter((obs) => obs !== void 0);
1525
1301
  }
1526
1302
  return [];
1527
1303
  }
1528
- function getChecksForContainer(inv, containerKey, recursive = false) {
1304
+ function findChecksForTag(inv, tagKey, recursive = false) {
1529
1305
  const result = [];
1530
- function findContainer(containers) {
1531
- for (const container2 of Object.values(containers)) {
1532
- if (container2.key === containerKey) {
1533
- return container2;
1534
- }
1535
- const found = findContainer(container2.sub_containers);
1536
- if (found) return found;
1306
+ const tag = inv.tags[tagKey];
1307
+ if (!tag) {
1308
+ return result;
1309
+ }
1310
+ for (const checkKey of tag.checks) {
1311
+ const check = inv.checks[checkKey];
1312
+ if (check) {
1313
+ result.push(check);
1537
1314
  }
1538
- return void 0;
1539
1315
  }
1540
- function collectChecks(container2) {
1541
- for (const checkKey of container2.checks) {
1542
- for (const checks of Object.values(inv.checks)) {
1543
- for (const check of checks) {
1544
- if (check.key === checkKey) {
1316
+ if (recursive) {
1317
+ const prefix = tag.name + ":";
1318
+ for (const otherTag of Object.values(inv.tags)) {
1319
+ if (otherTag.name.startsWith(prefix)) {
1320
+ for (const checkKey of otherTag.checks) {
1321
+ const check = inv.checks[checkKey];
1322
+ if (check) {
1545
1323
  result.push(check);
1546
1324
  }
1547
1325
  }
1548
1326
  }
1549
1327
  }
1550
- if (recursive) {
1551
- for (const subContainer of Object.values(container2.sub_containers)) {
1552
- collectChecks(subContainer);
1553
- }
1554
- }
1555
- }
1556
- const container = findContainer(inv.containers);
1557
- if (container) {
1558
- collectChecks(container);
1559
1328
  }
1560
1329
  return result;
1561
1330
  }
@@ -1575,29 +1344,25 @@ function sortChecksByLevel(checks) {
1575
1344
  (a, b) => LEVEL_VALUES[b.level] - LEVEL_VALUES[a.level]
1576
1345
  );
1577
1346
  }
1578
- function getHighestScoringObservables(inv, n = 10) {
1347
+ function findHighestScoringObservables(inv, n = 10) {
1579
1348
  return sortObservablesByScore(Object.values(inv.observables)).slice(0, n);
1580
1349
  }
1581
- function getHighestScoringChecks(inv, n = 10) {
1582
- const allChecks = [];
1583
- for (const checks of Object.values(inv.checks)) {
1584
- allChecks.push(...checks);
1585
- }
1586
- return sortChecksByScore(allChecks).slice(0, n);
1350
+ function findHighestScoringChecks(inv, n = 10) {
1351
+ return sortChecksByScore(Object.values(inv.checks)).slice(0, n);
1587
1352
  }
1588
- function getMaliciousObservables(inv) {
1353
+ function findMaliciousObservables(inv) {
1589
1354
  return findObservablesByLevel(inv, "MALICIOUS");
1590
1355
  }
1591
- function getSuspiciousObservables(inv) {
1356
+ function findSuspiciousObservables(inv) {
1592
1357
  return findObservablesByLevel(inv, "SUSPICIOUS");
1593
1358
  }
1594
- function getMaliciousChecks(inv) {
1359
+ function findMaliciousChecks(inv) {
1595
1360
  return findChecksByLevel(inv, "MALICIOUS");
1596
1361
  }
1597
- function getSuspiciousChecks(inv) {
1362
+ function findSuspiciousChecks(inv) {
1598
1363
  return findChecksByLevel(inv, "SUSPICIOUS");
1599
1364
  }
1600
- function getAllScopes(inv) {
1365
+ function getAllCheckKeys(inv) {
1601
1366
  return Object.keys(inv.checks);
1602
1367
  }
1603
1368
  function getAllObservableTypes(inv) {
@@ -1734,7 +1499,7 @@ function getObservableGraph(inv) {
1734
1499
  }
1735
1500
  return { nodes, edges };
1736
1501
  }
1737
- function findRootObservables(inv) {
1502
+ function findSourceObservables(inv) {
1738
1503
  const targetKeys = /* @__PURE__ */ new Set();
1739
1504
  for (const obs of Object.values(inv.observables)) {
1740
1505
  for (const rel of obs.relationships) {
@@ -1875,93 +1640,100 @@ function getRelationshipsForObservable(inv, observableKey) {
1875
1640
  ]
1876
1641
  };
1877
1642
  }
1878
- // Annotate the CommonJS export names for ESM import in node:
1879
- 0 && (module.exports = {
1643
+ export {
1880
1644
  LEVEL_COLORS,
1881
1645
  LEVEL_ORDER,
1882
1646
  LEVEL_VALUES,
1883
1647
  areConnected,
1884
1648
  compareLevels,
1885
1649
  countRelationshipsByType,
1650
+ findCheckByName,
1886
1651
  findChecksAtLeast,
1887
- findChecksByCheckId,
1888
1652
  findChecksByLevel,
1889
- findChecksByScope,
1890
- findContainersAtLeast,
1891
- findContainersByLevel,
1653
+ findChecksForObservable,
1654
+ findChecksForTag,
1892
1655
  findExternalObservables,
1656
+ findHighestScoringChecks,
1657
+ findHighestScoringObservables,
1893
1658
  findInternalObservables,
1894
1659
  findLeafObservables,
1660
+ findMaliciousChecks,
1661
+ findMaliciousObservables,
1895
1662
  findObservablesAtLeast,
1896
1663
  findObservablesByLevel,
1897
1664
  findObservablesByType,
1898
1665
  findObservablesByValue,
1899
1666
  findObservablesContaining,
1667
+ findObservablesForCheck,
1900
1668
  findObservablesMatching,
1901
1669
  findObservablesWithThreatIntel,
1902
1670
  findOrphanObservables,
1903
1671
  findPath,
1904
- findRootObservables,
1672
+ findSourceObservables,
1673
+ findSuspiciousChecks,
1674
+ findSuspiciousObservables,
1675
+ findTagsAtLeast,
1676
+ findTagsByLevel,
1677
+ findTagsByNamePattern,
1905
1678
  findThreatIntelAtLeast,
1906
1679
  findThreatIntelByLevel,
1907
1680
  findThreatIntelBySource,
1681
+ findThreatIntelsForObservable,
1908
1682
  findWhitelistedObservables,
1909
1683
  generateCheckKey,
1910
- generateContainerKey,
1911
1684
  generateEnrichmentKey,
1912
1685
  generateObservableKey,
1686
+ generateTagKey,
1913
1687
  generateThreatIntelKey,
1688
+ getAllCheckKeys,
1914
1689
  getAllChecks,
1915
- getAllContainers,
1916
1690
  getAllEnrichments,
1917
1691
  getAllObservableTypes,
1918
1692
  getAllObservables,
1919
1693
  getAllRelationshipTypes,
1920
- getAllScopes,
1694
+ getAllTags,
1921
1695
  getAllThreatIntelSources,
1922
1696
  getAllThreatIntels,
1923
1697
  getCheck,
1924
- getCheckByIdScope,
1925
- getChecksForContainer,
1926
- getChecksForObservable,
1698
+ getCheckByName,
1927
1699
  getColorForLevel,
1928
1700
  getColorForScore,
1929
- getContainer,
1930
- getContainerByPath,
1931
1701
  getCounts,
1932
1702
  getDataExtraction,
1933
1703
  getEnrichment,
1934
1704
  getEnrichmentByName,
1935
1705
  getEntityLevel,
1936
- getHighestScoringChecks,
1937
- getHighestScoringObservables,
1938
1706
  getLevelFromScore,
1939
- getMaliciousChecks,
1940
- getMaliciousObservables,
1941
1707
  getObservable,
1942
1708
  getObservableByTypeValue,
1943
1709
  getObservableChildren,
1944
1710
  getObservableGraph,
1945
1711
  getObservableParents,
1946
- getObservablesForCheck,
1947
1712
  getReachableObservables,
1948
1713
  getRelatedObservables,
1949
1714
  getRelatedObservablesByDirection,
1950
1715
  getRelatedObservablesByType,
1951
1716
  getRelationshipsForObservable,
1717
+ getRootObservable,
1952
1718
  getStartedAt,
1953
1719
  getStats,
1954
- getSuspiciousChecks,
1955
- getSuspiciousObservables,
1720
+ getTag,
1721
+ getTagAggregatedLevel,
1722
+ getTagAggregatedScore,
1723
+ getTagAncestors,
1724
+ getTagByName,
1725
+ getTagChildren,
1726
+ getTagDescendants,
1956
1727
  getThreatIntel,
1957
1728
  getThreatIntelBySourceObservable,
1958
- getThreatIntelsForObservable,
1959
1729
  getWhitelists,
1960
1730
  hasLevel,
1961
1731
  isCyvest,
1962
1732
  isLevelAtLeast,
1963
1733
  isLevelHigherThan,
1964
1734
  isLevelLowerThan,
1735
+ isTagChildOf,
1736
+ isTagDescendantOf,
1965
1737
  isValidLevel,
1966
1738
  maxLevel,
1967
1739
  minLevel,
@@ -1976,4 +1748,4 @@ function getRelationshipsForObservable(inv, observableKey) {
1976
1748
  sortObservablesByLevel,
1977
1749
  sortObservablesByScore,
1978
1750
  validateKey
1979
- });
1751
+ };