@cyvest/cyvest-js 4.4.1 → 5.0.2

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,85 +36,93 @@ __export(index_exports, {
36
36
  areConnected: () => areConnected,
37
37
  compareLevels: () => compareLevels,
38
38
  countRelationshipsByType: () => countRelationshipsByType,
39
+ findCheckByName: () => findCheckByName,
39
40
  findChecksAtLeast: () => findChecksAtLeast,
40
- findChecksByCheckId: () => findChecksByCheckId,
41
41
  findChecksByLevel: () => findChecksByLevel,
42
- findChecksByScope: () => findChecksByScope,
43
- findContainersAtLeast: () => findContainersAtLeast,
44
- findContainersByLevel: () => findContainersByLevel,
42
+ findChecksForObservable: () => findChecksForObservable,
43
+ findChecksForTag: () => findChecksForTag,
45
44
  findExternalObservables: () => findExternalObservables,
45
+ findHighestScoringChecks: () => findHighestScoringChecks,
46
+ findHighestScoringObservables: () => findHighestScoringObservables,
46
47
  findInternalObservables: () => findInternalObservables,
47
48
  findLeafObservables: () => findLeafObservables,
49
+ findMaliciousChecks: () => findMaliciousChecks,
50
+ findMaliciousObservables: () => findMaliciousObservables,
48
51
  findObservablesAtLeast: () => findObservablesAtLeast,
49
52
  findObservablesByLevel: () => findObservablesByLevel,
50
53
  findObservablesByType: () => findObservablesByType,
51
54
  findObservablesByValue: () => findObservablesByValue,
52
55
  findObservablesContaining: () => findObservablesContaining,
56
+ findObservablesForCheck: () => findObservablesForCheck,
53
57
  findObservablesMatching: () => findObservablesMatching,
54
58
  findObservablesWithThreatIntel: () => findObservablesWithThreatIntel,
55
59
  findOrphanObservables: () => findOrphanObservables,
56
60
  findPath: () => findPath,
57
- findRootObservables: () => findRootObservables,
61
+ findSourceObservables: () => findSourceObservables,
62
+ findSuspiciousChecks: () => findSuspiciousChecks,
63
+ findSuspiciousObservables: () => findSuspiciousObservables,
64
+ findTagsAtLeast: () => findTagsAtLeast,
65
+ findTagsByLevel: () => findTagsByLevel,
66
+ findTagsByNamePattern: () => findTagsByNamePattern,
58
67
  findThreatIntelAtLeast: () => findThreatIntelAtLeast,
59
68
  findThreatIntelByLevel: () => findThreatIntelByLevel,
60
69
  findThreatIntelBySource: () => findThreatIntelBySource,
70
+ findThreatIntelsForObservable: () => findThreatIntelsForObservable,
61
71
  findWhitelistedObservables: () => findWhitelistedObservables,
62
72
  generateCheckKey: () => generateCheckKey,
63
- generateContainerKey: () => generateContainerKey,
64
73
  generateEnrichmentKey: () => generateEnrichmentKey,
65
74
  generateObservableKey: () => generateObservableKey,
75
+ generateTagKey: () => generateTagKey,
66
76
  generateThreatIntelKey: () => generateThreatIntelKey,
77
+ getAllCheckKeys: () => getAllCheckKeys,
67
78
  getAllChecks: () => getAllChecks,
68
- getAllContainers: () => getAllContainers,
69
79
  getAllEnrichments: () => getAllEnrichments,
70
80
  getAllObservableTypes: () => getAllObservableTypes,
71
81
  getAllObservables: () => getAllObservables,
72
82
  getAllRelationshipTypes: () => getAllRelationshipTypes,
73
- getAllScopes: () => getAllScopes,
83
+ getAllTags: () => getAllTags,
74
84
  getAllThreatIntelSources: () => getAllThreatIntelSources,
75
85
  getAllThreatIntels: () => getAllThreatIntels,
76
86
  getCheck: () => getCheck,
77
- getCheckByIdScope: () => getCheckByIdScope,
78
- getChecksForContainer: () => getChecksForContainer,
79
- getChecksForObservable: () => getChecksForObservable,
87
+ getCheckByName: () => getCheckByName,
80
88
  getColorForLevel: () => getColorForLevel,
81
89
  getColorForScore: () => getColorForScore,
82
- getContainer: () => getContainer,
83
- getContainerByPath: () => getContainerByPath,
84
90
  getCounts: () => getCounts,
85
91
  getDataExtraction: () => getDataExtraction,
86
92
  getEnrichment: () => getEnrichment,
87
93
  getEnrichmentByName: () => getEnrichmentByName,
88
94
  getEntityLevel: () => getEntityLevel,
89
- getHighestScoringChecks: () => getHighestScoringChecks,
90
- getHighestScoringObservables: () => getHighestScoringObservables,
91
95
  getLevelFromScore: () => getLevelFromScore,
92
- getMaliciousChecks: () => getMaliciousChecks,
93
- getMaliciousObservables: () => getMaliciousObservables,
94
96
  getObservable: () => getObservable,
95
97
  getObservableByTypeValue: () => getObservableByTypeValue,
96
98
  getObservableChildren: () => getObservableChildren,
97
99
  getObservableGraph: () => getObservableGraph,
98
100
  getObservableParents: () => getObservableParents,
99
- getObservablesForCheck: () => getObservablesForCheck,
100
101
  getReachableObservables: () => getReachableObservables,
101
102
  getRelatedObservables: () => getRelatedObservables,
102
103
  getRelatedObservablesByDirection: () => getRelatedObservablesByDirection,
103
104
  getRelatedObservablesByType: () => getRelatedObservablesByType,
104
105
  getRelationshipsForObservable: () => getRelationshipsForObservable,
106
+ getRootObservable: () => getRootObservable,
105
107
  getStartedAt: () => getStartedAt,
106
108
  getStats: () => getStats,
107
- getSuspiciousChecks: () => getSuspiciousChecks,
108
- getSuspiciousObservables: () => getSuspiciousObservables,
109
+ getTag: () => getTag,
110
+ getTagAggregatedLevel: () => getTagAggregatedLevel,
111
+ getTagAggregatedScore: () => getTagAggregatedScore,
112
+ getTagAncestors: () => getTagAncestors,
113
+ getTagByName: () => getTagByName,
114
+ getTagChildren: () => getTagChildren,
115
+ getTagDescendants: () => getTagDescendants,
109
116
  getThreatIntel: () => getThreatIntel,
110
117
  getThreatIntelBySourceObservable: () => getThreatIntelBySourceObservable,
111
- getThreatIntelsForObservable: () => getThreatIntelsForObservable,
112
118
  getWhitelists: () => getWhitelists,
113
119
  hasLevel: () => hasLevel,
114
120
  isCyvest: () => isCyvest,
115
121
  isLevelAtLeast: () => isLevelAtLeast,
116
122
  isLevelHigherThan: () => isLevelHigherThan,
117
123
  isLevelLowerThan: () => isLevelLowerThan,
124
+ isTagChildOf: () => isTagChildOf,
125
+ isTagDescendantOf: () => isTagDescendantOf,
118
126
  isValidLevel: () => isValidLevel,
119
127
  maxLevel: () => maxLevel,
120
128
  minLevel: () => minLevel,
@@ -233,12 +241,8 @@ var cyvest_schema_default = {
233
241
  Check: {
234
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.",
235
243
  properties: {
236
- check_id: {
237
- title: "Check Id",
238
- type: "string"
239
- },
240
- scope: {
241
- title: "Scope",
244
+ check_name: {
245
+ title: "Check Name",
242
246
  type: "string"
243
247
  },
244
248
  description: {
@@ -283,8 +287,7 @@ var cyvest_schema_default = {
283
287
  }
284
288
  },
285
289
  required: [
286
- "check_id",
287
- "scope",
290
+ "check_name",
288
291
  "description",
289
292
  "comment",
290
293
  "extra",
@@ -298,59 +301,6 @@ var cyvest_schema_default = {
298
301
  title: "Check",
299
302
  type: "object"
300
303
  },
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
304
  DataExtractionSchema: {
355
305
  additionalProperties: false,
356
306
  description: "Schema for data extraction metadata.",
@@ -675,16 +625,6 @@ var cyvest_schema_default = {
675
625
  title: "Applied Checks",
676
626
  type: "integer"
677
627
  },
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
628
  checks_by_level: {
689
629
  additionalProperties: {
690
630
  items: {
@@ -716,9 +656,9 @@ var cyvest_schema_default = {
716
656
  title: "Threat Intel By Level",
717
657
  type: "object"
718
658
  },
719
- total_containers: {
659
+ total_tags: {
720
660
  minimum: 0,
721
- title: "Total Containers",
661
+ title: "Total Tags",
722
662
  type: "integer"
723
663
  }
724
664
  },
@@ -730,11 +670,57 @@ var cyvest_schema_default = {
730
670
  "total_checks",
731
671
  "applied_checks",
732
672
  "total_threat_intel",
733
- "total_containers"
673
+ "total_tags"
734
674
  ],
735
675
  title: "StatisticsSchema",
736
676
  type: "object"
737
677
  },
678
+ Tag: {
679
+ 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").',
681
+ properties: {
682
+ name: {
683
+ title: "Name",
684
+ type: "string"
685
+ },
686
+ description: {
687
+ default: "",
688
+ title: "Description",
689
+ type: "string"
690
+ },
691
+ checks: {
692
+ items: {
693
+ type: "string"
694
+ },
695
+ title: "Checks",
696
+ type: "array"
697
+ },
698
+ key: {
699
+ title: "Key",
700
+ type: "string"
701
+ },
702
+ 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",
704
+ readOnly: true,
705
+ title: "Direct Score",
706
+ type: "number"
707
+ },
708
+ direct_level: {
709
+ $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",
711
+ readOnly: true
712
+ }
713
+ },
714
+ required: [
715
+ "name",
716
+ "checks",
717
+ "key",
718
+ "direct_score",
719
+ "direct_level"
720
+ ],
721
+ title: "Tag",
722
+ type: "object"
723
+ },
738
724
  Taxonomy: {
739
725
  additionalProperties: false,
740
726
  description: "Represents a structured taxonomy entry for threat intelligence.",
@@ -888,12 +874,9 @@ var cyvest_schema_default = {
888
874
  },
889
875
  checks: {
890
876
  additionalProperties: {
891
- items: {
892
- $ref: "#/$defs/Check"
893
- },
894
- type: "array"
877
+ $ref: "#/$defs/Check"
895
878
  },
896
- description: "Checks organized by scope.",
879
+ description: "Checks keyed by their unique key.",
897
880
  title: "Checks",
898
881
  type: "object"
899
882
  },
@@ -913,12 +896,12 @@ var cyvest_schema_default = {
913
896
  title: "Enrichments",
914
897
  type: "object"
915
898
  },
916
- containers: {
899
+ tags: {
917
900
  additionalProperties: {
918
- $ref: "#/$defs/Container"
901
+ $ref: "#/$defs/Tag"
919
902
  },
920
- description: "Containers keyed by their unique key.",
921
- title: "Containers",
903
+ description: "Tags keyed by their unique key.",
904
+ title: "Tags",
922
905
  type: "object"
923
906
  },
924
907
  stats: {
@@ -946,7 +929,7 @@ var cyvest_schema_default = {
946
929
  "checks",
947
930
  "threat_intels",
948
931
  "enrichments",
949
- "containers",
932
+ "tags",
950
933
  "stats",
951
934
  "data_extraction",
952
935
  "score_display"
@@ -996,10 +979,9 @@ function generateObservableKey(obsType, value) {
996
979
  const normalizedValue = normalizeValue(value);
997
980
  return `obs:${normalizedType}:${normalizedValue}`;
998
981
  }
999
- function generateCheckKey(checkId, scope) {
1000
- const normalizedId = normalizeValue(checkId);
1001
- const normalizedScope = normalizeValue(scope);
1002
- return `chk:${normalizedId}:${normalizedScope}`;
982
+ function generateCheckKey(checkName) {
983
+ const normalizedName = normalizeValue(checkName);
984
+ return `chk:${normalizedName}`;
1003
985
  }
1004
986
  function generateThreatIntelKey(source, observableKey) {
1005
987
  const normalizedSource = normalizeValue(source);
@@ -1013,15 +995,32 @@ function generateEnrichmentKey(name, context) {
1013
995
  }
1014
996
  return `enr:${normalizedName}`;
1015
997
  }
1016
- function generateContainerKey(path) {
1017
- let normalizedPath = path.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
1018
- normalizedPath = normalizeValue(normalizedPath);
1019
- return `ctr:${normalizedPath}`;
998
+ function generateTagKey(name) {
999
+ const normalizedName = normalizeValue(name);
1000
+ return `tag:${normalizedName}`;
1001
+ }
1002
+ function getTagAncestors(name) {
1003
+ const parts = name.split(":");
1004
+ const ancestors = [];
1005
+ for (let i = 0; i < parts.length - 1; i++) {
1006
+ ancestors.push(parts.slice(0, i + 1).join(":"));
1007
+ }
1008
+ return ancestors;
1009
+ }
1010
+ function isTagChildOf(childName, parentName) {
1011
+ if (!childName.startsWith(parentName + ":")) {
1012
+ return false;
1013
+ }
1014
+ const remaining = childName.slice(parentName.length + 1);
1015
+ return !remaining.includes(":");
1016
+ }
1017
+ function isTagDescendantOf(descendantName, ancestorName) {
1018
+ return descendantName.startsWith(ancestorName + ":");
1020
1019
  }
1021
1020
  function parseKeyType(key) {
1022
1021
  if (key.includes(":")) {
1023
1022
  const prefix = key.split(":", 1)[0];
1024
- if (["obs", "chk", "ti", "enr", "ctr"].includes(prefix)) {
1023
+ if (["obs", "chk", "ti", "enr", "tag"].includes(prefix)) {
1025
1024
  return prefix;
1026
1025
  }
1027
1026
  }
@@ -1059,10 +1058,9 @@ function parseCheckKey(key) {
1059
1058
  return null;
1060
1059
  }
1061
1060
  const parts = key.split(":");
1062
- if (parts.length >= 3) {
1061
+ if (parts.length >= 2) {
1063
1062
  return {
1064
- checkId: parts[1],
1065
- scope: parts.slice(2).join(":")
1063
+ checkName: parts.slice(1).join(":")
1066
1064
  };
1067
1065
  }
1068
1066
  return null;
@@ -1179,10 +1177,10 @@ function hasLevel(obj) {
1179
1177
  return typeof obj === "object" && obj !== null && "level" in obj && typeof obj.level === "string" && isValidLevel(obj.level);
1180
1178
  }
1181
1179
  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;
1180
+ if ("direct_level" in entity) {
1181
+ const directLevel = entity.direct_level;
1182
+ if (typeof directLevel === "string" && isValidLevel(directLevel)) {
1183
+ return directLevel;
1186
1184
  }
1187
1185
  }
1188
1186
  if ("level" in entity && isValidLevel(entity.level)) {
@@ -1205,40 +1203,24 @@ function getObservableByTypeValue(inv, type, value) {
1205
1203
  }
1206
1204
  return void 0;
1207
1205
  }
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
- }
1206
+ function getRootObservable(inv) {
1207
+ const rootType = inv.data_extraction.root_type;
1208
+ if (!rootType) {
1209
+ return void 0;
1215
1210
  }
1216
- return void 0;
1211
+ const rootKey = generateObservableKey(rootType, "root");
1212
+ return inv.observables[rootKey];
1217
1213
  }
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;
1214
+ function getCheck(inv, key) {
1215
+ return inv.checks[key];
1216
+ }
1217
+ function getCheckByName(inv, checkName) {
1218
+ const normalizedName = checkName.trim().toLowerCase();
1219
+ const key = `chk:${normalizedName}`;
1220
+ return inv.checks[key];
1235
1221
  }
1236
1222
  function getAllChecks(inv) {
1237
- const result = [];
1238
- for (const checks of Object.values(inv.checks)) {
1239
- result.push(...checks);
1240
- }
1241
- return result;
1223
+ return Object.values(inv.checks);
1242
1224
  }
1243
1225
  function getThreatIntel(inv, key) {
1244
1226
  return inv.threat_intels[key];
@@ -1270,46 +1252,16 @@ function getEnrichmentByName(inv, name) {
1270
1252
  function getAllEnrichments(inv) {
1271
1253
  return Object.values(inv.enrichments);
1272
1254
  }
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);
1255
+ function getTag(inv, key) {
1256
+ return inv.tags[key];
1302
1257
  }
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;
1258
+ function getTagByName(inv, name) {
1259
+ const normalizedName = name.trim().toLowerCase();
1260
+ const key = `tag:${normalizedName}`;
1261
+ return inv.tags[key];
1262
+ }
1263
+ function getAllTags(inv) {
1264
+ return Object.values(inv.tags);
1313
1265
  }
1314
1266
  function getAllObservables(inv) {
1315
1267
  return Object.values(inv.observables);
@@ -1329,7 +1281,7 @@ function getCounts(inv) {
1329
1281
  checks: getAllChecks(inv).length,
1330
1282
  threatIntels: Object.keys(inv.threat_intels).length,
1331
1283
  enrichments: Object.keys(inv.enrichments).length,
1332
- containers: getAllContainers(inv).length,
1284
+ tags: getAllTags(inv).length,
1333
1285
  whitelists: inv.whitelists.length
1334
1286
  };
1335
1287
  }
@@ -1339,6 +1291,28 @@ function getStartedAt(inv) {
1339
1291
  );
1340
1292
  return event?.timestamp;
1341
1293
  }
1294
+ function getTagChildren(inv, tagName) {
1295
+ return Object.values(inv.tags).filter((tag) => isTagChildOf(tag.name, tagName));
1296
+ }
1297
+ function getTagDescendants(inv, tagName) {
1298
+ const prefix = tagName + ":";
1299
+ return Object.values(inv.tags).filter((tag) => tag.name.startsWith(prefix));
1300
+ }
1301
+ function getTagAggregatedScore(inv, tagName) {
1302
+ const tag = getTagByName(inv, tagName);
1303
+ if (!tag) {
1304
+ return 0;
1305
+ }
1306
+ let total = tag.direct_score;
1307
+ const children = getTagChildren(inv, tagName);
1308
+ for (const child of children) {
1309
+ total += getTagAggregatedScore(inv, child.name);
1310
+ }
1311
+ return total;
1312
+ }
1313
+ function getTagAggregatedLevel(inv, tagName) {
1314
+ return getLevelFromScore(getTagAggregatedScore(inv, tagName));
1315
+ }
1342
1316
 
1343
1317
  // src/finders.ts
1344
1318
  function findObservablesByType(inv, type) {
@@ -1386,51 +1360,19 @@ function findObservablesWithThreatIntel(inv) {
1386
1360
  (obs) => obs.threat_intels.length > 0
1387
1361
  );
1388
1362
  }
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
1363
  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;
1364
+ return Object.values(inv.checks).filter((check) => check.level === level);
1411
1365
  }
1412
1366
  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;
1367
+ return Object.values(inv.checks).filter(
1368
+ (check) => isLevelAtLeast(check.level, minLevel2)
1369
+ );
1422
1370
  }
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;
1371
+ function findCheckByName(inv, checkName) {
1372
+ const normalizedName = checkName.trim().toLowerCase();
1373
+ return Object.values(inv.checks).find(
1374
+ (check) => check.check_name.toLowerCase() === normalizedName
1375
+ );
1434
1376
  }
1435
1377
  function findThreatIntelBySource(inv, source) {
1436
1378
  const normalizedSource = source.trim().toLowerCase();
@@ -1446,52 +1388,31 @@ function findThreatIntelAtLeast(inv, minLevel2) {
1446
1388
  (ti) => isLevelAtLeast(ti.level, minLevel2)
1447
1389
  );
1448
1390
  }
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;
1391
+ function findTagsByLevel(inv, level) {
1392
+ return Object.values(inv.tags).filter((tag) => tag.direct_level === level);
1461
1393
  }
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;
1394
+ function findTagsAtLeast(inv, minLevel2) {
1395
+ return Object.values(inv.tags).filter(
1396
+ (tag) => isLevelAtLeast(tag.direct_level, minLevel2)
1397
+ );
1474
1398
  }
1475
- function getChecksForObservable(inv, observableKey) {
1399
+ function findTagsByNamePattern(inv, pattern) {
1400
+ return Object.values(inv.tags).filter((tag) => pattern.test(tag.name));
1401
+ }
1402
+ function findChecksForObservable(inv, observableKey) {
1476
1403
  const result = [];
1477
1404
  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
1405
  const observable = inv.observables[observableKey];
1485
1406
  if (observable) {
1486
1407
  for (const checkKey of observable.check_links) {
1487
- const check = checkLookup.get(checkKey);
1408
+ const check = inv.checks[checkKey];
1488
1409
  if (check && !seen.has(check.key)) {
1489
1410
  result.push(check);
1490
1411
  seen.add(check.key);
1491
1412
  }
1492
1413
  }
1493
1414
  }
1494
- for (const check of checkLookup.values()) {
1415
+ for (const check of Object.values(inv.checks)) {
1495
1416
  if (seen.has(check.key)) {
1496
1417
  continue;
1497
1418
  }
@@ -1502,7 +1423,7 @@ function getChecksForObservable(inv, observableKey) {
1502
1423
  }
1503
1424
  return result;
1504
1425
  }
1505
- function getThreatIntelsForObservable(inv, observableKey) {
1426
+ function findThreatIntelsForObservable(inv, observableKey) {
1506
1427
  const observable = inv.observables[observableKey];
1507
1428
  if (observable) {
1508
1429
  return observable.threat_intels.map((tiKey) => inv.threat_intels[tiKey]).filter((ti) => ti !== void 0);
@@ -1511,51 +1432,41 @@ function getThreatIntelsForObservable(inv, observableKey) {
1511
1432
  (ti) => ti.observable_key === observableKey
1512
1433
  );
1513
1434
  }
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
- }
1435
+ function findObservablesForCheck(inv, checkKey) {
1436
+ const check = inv.checks[checkKey];
1437
+ if (check) {
1438
+ const keys = /* @__PURE__ */ new Set();
1439
+ for (const link of check.observable_links) {
1440
+ keys.add(link.observable_key);
1524
1441
  }
1442
+ return Array.from(keys).map((obsKey) => inv.observables[obsKey]).filter((obs) => obs !== void 0);
1525
1443
  }
1526
1444
  return [];
1527
1445
  }
1528
- function getChecksForContainer(inv, containerKey, recursive = false) {
1446
+ function findChecksForTag(inv, tagKey, recursive = false) {
1529
1447
  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;
1448
+ const tag = inv.tags[tagKey];
1449
+ if (!tag) {
1450
+ return result;
1451
+ }
1452
+ for (const checkKey of tag.checks) {
1453
+ const check = inv.checks[checkKey];
1454
+ if (check) {
1455
+ result.push(check);
1537
1456
  }
1538
- return void 0;
1539
1457
  }
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) {
1458
+ if (recursive) {
1459
+ const prefix = tag.name + ":";
1460
+ for (const otherTag of Object.values(inv.tags)) {
1461
+ if (otherTag.name.startsWith(prefix)) {
1462
+ for (const checkKey of otherTag.checks) {
1463
+ const check = inv.checks[checkKey];
1464
+ if (check) {
1545
1465
  result.push(check);
1546
1466
  }
1547
1467
  }
1548
1468
  }
1549
1469
  }
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
1470
  }
1560
1471
  return result;
1561
1472
  }
@@ -1575,29 +1486,25 @@ function sortChecksByLevel(checks) {
1575
1486
  (a, b) => LEVEL_VALUES[b.level] - LEVEL_VALUES[a.level]
1576
1487
  );
1577
1488
  }
1578
- function getHighestScoringObservables(inv, n = 10) {
1489
+ function findHighestScoringObservables(inv, n = 10) {
1579
1490
  return sortObservablesByScore(Object.values(inv.observables)).slice(0, n);
1580
1491
  }
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);
1492
+ function findHighestScoringChecks(inv, n = 10) {
1493
+ return sortChecksByScore(Object.values(inv.checks)).slice(0, n);
1587
1494
  }
1588
- function getMaliciousObservables(inv) {
1495
+ function findMaliciousObservables(inv) {
1589
1496
  return findObservablesByLevel(inv, "MALICIOUS");
1590
1497
  }
1591
- function getSuspiciousObservables(inv) {
1498
+ function findSuspiciousObservables(inv) {
1592
1499
  return findObservablesByLevel(inv, "SUSPICIOUS");
1593
1500
  }
1594
- function getMaliciousChecks(inv) {
1501
+ function findMaliciousChecks(inv) {
1595
1502
  return findChecksByLevel(inv, "MALICIOUS");
1596
1503
  }
1597
- function getSuspiciousChecks(inv) {
1504
+ function findSuspiciousChecks(inv) {
1598
1505
  return findChecksByLevel(inv, "SUSPICIOUS");
1599
1506
  }
1600
- function getAllScopes(inv) {
1507
+ function getAllCheckKeys(inv) {
1601
1508
  return Object.keys(inv.checks);
1602
1509
  }
1603
1510
  function getAllObservableTypes(inv) {
@@ -1734,7 +1641,7 @@ function getObservableGraph(inv) {
1734
1641
  }
1735
1642
  return { nodes, edges };
1736
1643
  }
1737
- function findRootObservables(inv) {
1644
+ function findSourceObservables(inv) {
1738
1645
  const targetKeys = /* @__PURE__ */ new Set();
1739
1646
  for (const obs of Object.values(inv.observables)) {
1740
1647
  for (const rel of obs.relationships) {
@@ -1883,85 +1790,93 @@ function getRelationshipsForObservable(inv, observableKey) {
1883
1790
  areConnected,
1884
1791
  compareLevels,
1885
1792
  countRelationshipsByType,
1793
+ findCheckByName,
1886
1794
  findChecksAtLeast,
1887
- findChecksByCheckId,
1888
1795
  findChecksByLevel,
1889
- findChecksByScope,
1890
- findContainersAtLeast,
1891
- findContainersByLevel,
1796
+ findChecksForObservable,
1797
+ findChecksForTag,
1892
1798
  findExternalObservables,
1799
+ findHighestScoringChecks,
1800
+ findHighestScoringObservables,
1893
1801
  findInternalObservables,
1894
1802
  findLeafObservables,
1803
+ findMaliciousChecks,
1804
+ findMaliciousObservables,
1895
1805
  findObservablesAtLeast,
1896
1806
  findObservablesByLevel,
1897
1807
  findObservablesByType,
1898
1808
  findObservablesByValue,
1899
1809
  findObservablesContaining,
1810
+ findObservablesForCheck,
1900
1811
  findObservablesMatching,
1901
1812
  findObservablesWithThreatIntel,
1902
1813
  findOrphanObservables,
1903
1814
  findPath,
1904
- findRootObservables,
1815
+ findSourceObservables,
1816
+ findSuspiciousChecks,
1817
+ findSuspiciousObservables,
1818
+ findTagsAtLeast,
1819
+ findTagsByLevel,
1820
+ findTagsByNamePattern,
1905
1821
  findThreatIntelAtLeast,
1906
1822
  findThreatIntelByLevel,
1907
1823
  findThreatIntelBySource,
1824
+ findThreatIntelsForObservable,
1908
1825
  findWhitelistedObservables,
1909
1826
  generateCheckKey,
1910
- generateContainerKey,
1911
1827
  generateEnrichmentKey,
1912
1828
  generateObservableKey,
1829
+ generateTagKey,
1913
1830
  generateThreatIntelKey,
1831
+ getAllCheckKeys,
1914
1832
  getAllChecks,
1915
- getAllContainers,
1916
1833
  getAllEnrichments,
1917
1834
  getAllObservableTypes,
1918
1835
  getAllObservables,
1919
1836
  getAllRelationshipTypes,
1920
- getAllScopes,
1837
+ getAllTags,
1921
1838
  getAllThreatIntelSources,
1922
1839
  getAllThreatIntels,
1923
1840
  getCheck,
1924
- getCheckByIdScope,
1925
- getChecksForContainer,
1926
- getChecksForObservable,
1841
+ getCheckByName,
1927
1842
  getColorForLevel,
1928
1843
  getColorForScore,
1929
- getContainer,
1930
- getContainerByPath,
1931
1844
  getCounts,
1932
1845
  getDataExtraction,
1933
1846
  getEnrichment,
1934
1847
  getEnrichmentByName,
1935
1848
  getEntityLevel,
1936
- getHighestScoringChecks,
1937
- getHighestScoringObservables,
1938
1849
  getLevelFromScore,
1939
- getMaliciousChecks,
1940
- getMaliciousObservables,
1941
1850
  getObservable,
1942
1851
  getObservableByTypeValue,
1943
1852
  getObservableChildren,
1944
1853
  getObservableGraph,
1945
1854
  getObservableParents,
1946
- getObservablesForCheck,
1947
1855
  getReachableObservables,
1948
1856
  getRelatedObservables,
1949
1857
  getRelatedObservablesByDirection,
1950
1858
  getRelatedObservablesByType,
1951
1859
  getRelationshipsForObservable,
1860
+ getRootObservable,
1952
1861
  getStartedAt,
1953
1862
  getStats,
1954
- getSuspiciousChecks,
1955
- getSuspiciousObservables,
1863
+ getTag,
1864
+ getTagAggregatedLevel,
1865
+ getTagAggregatedScore,
1866
+ getTagAncestors,
1867
+ getTagByName,
1868
+ getTagChildren,
1869
+ getTagDescendants,
1956
1870
  getThreatIntel,
1957
1871
  getThreatIntelBySourceObservable,
1958
- getThreatIntelsForObservable,
1959
1872
  getWhitelists,
1960
1873
  hasLevel,
1961
1874
  isCyvest,
1962
1875
  isLevelAtLeast,
1963
1876
  isLevelHigherThan,
1964
1877
  isLevelLowerThan,
1878
+ isTagChildOf,
1879
+ isTagDescendantOf,
1965
1880
  isValidLevel,
1966
1881
  maxLevel,
1967
1882
  minLevel,