@cyvest/cyvest-js 4.4.1 → 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/README.md +5 -4
- package/dist/index.cjs +248 -333
- package/dist/index.d.cts +255 -121
- package/dist/index.d.ts +255 -121
- package/dist/index.js +219 -312
- package/package.json +1 -1
- package/src/finders.ts +101 -186
- package/src/getters.ts +176 -104
- package/src/graph.ts +4 -4
- package/src/keys.ts +84 -30
- package/src/levels.ts +7 -7
- package/src/types.generated.ts +25 -24
- package/tests/getters-finders.test.ts +225 -126
- package/tests/graph.test.ts +6 -7
- package/tests/keys-levels.test.ts +14 -15
package/dist/index.js
CHANGED
|
@@ -99,12 +99,8 @@ var cyvest_schema_default = {
|
|
|
99
99
|
Check: {
|
|
100
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.",
|
|
101
101
|
properties: {
|
|
102
|
-
|
|
103
|
-
title: "Check
|
|
104
|
-
type: "string"
|
|
105
|
-
},
|
|
106
|
-
scope: {
|
|
107
|
-
title: "Scope",
|
|
102
|
+
check_name: {
|
|
103
|
+
title: "Check Name",
|
|
108
104
|
type: "string"
|
|
109
105
|
},
|
|
110
106
|
description: {
|
|
@@ -149,8 +145,7 @@ var cyvest_schema_default = {
|
|
|
149
145
|
}
|
|
150
146
|
},
|
|
151
147
|
required: [
|
|
152
|
-
"
|
|
153
|
-
"scope",
|
|
148
|
+
"check_name",
|
|
154
149
|
"description",
|
|
155
150
|
"comment",
|
|
156
151
|
"extra",
|
|
@@ -164,59 +159,6 @@ var cyvest_schema_default = {
|
|
|
164
159
|
title: "Check",
|
|
165
160
|
type: "object"
|
|
166
161
|
},
|
|
167
|
-
Container: {
|
|
168
|
-
additionalProperties: false,
|
|
169
|
-
description: "Groups checks and sub-containers for hierarchical organization.\n\nContainers allow structuring the investigation into logical sections\nwith aggregated scores and levels.",
|
|
170
|
-
properties: {
|
|
171
|
-
path: {
|
|
172
|
-
title: "Path",
|
|
173
|
-
type: "string"
|
|
174
|
-
},
|
|
175
|
-
description: {
|
|
176
|
-
default: "",
|
|
177
|
-
title: "Description",
|
|
178
|
-
type: "string"
|
|
179
|
-
},
|
|
180
|
-
checks: {
|
|
181
|
-
items: {
|
|
182
|
-
type: "string"
|
|
183
|
-
},
|
|
184
|
-
title: "Checks",
|
|
185
|
-
type: "array"
|
|
186
|
-
},
|
|
187
|
-
sub_containers: {
|
|
188
|
-
additionalProperties: {
|
|
189
|
-
$ref: "#/$defs/Container"
|
|
190
|
-
},
|
|
191
|
-
title: "Sub Containers",
|
|
192
|
-
type: "object"
|
|
193
|
-
},
|
|
194
|
-
key: {
|
|
195
|
-
title: "Key",
|
|
196
|
-
type: "string"
|
|
197
|
-
},
|
|
198
|
-
aggregated_score: {
|
|
199
|
-
readOnly: true,
|
|
200
|
-
title: "Aggregated Score",
|
|
201
|
-
type: "number"
|
|
202
|
-
},
|
|
203
|
-
aggregated_level: {
|
|
204
|
-
$ref: "#/$defs/Level",
|
|
205
|
-
description: "Calculate the aggregated level from the aggregated score.\n\nReturns:\n Level based on aggregated score",
|
|
206
|
-
readOnly: true
|
|
207
|
-
}
|
|
208
|
-
},
|
|
209
|
-
required: [
|
|
210
|
-
"path",
|
|
211
|
-
"checks",
|
|
212
|
-
"sub_containers",
|
|
213
|
-
"key",
|
|
214
|
-
"aggregated_score",
|
|
215
|
-
"aggregated_level"
|
|
216
|
-
],
|
|
217
|
-
title: "Container",
|
|
218
|
-
type: "object"
|
|
219
|
-
},
|
|
220
162
|
DataExtractionSchema: {
|
|
221
163
|
additionalProperties: false,
|
|
222
164
|
description: "Schema for data extraction metadata.",
|
|
@@ -541,16 +483,6 @@ var cyvest_schema_default = {
|
|
|
541
483
|
title: "Applied Checks",
|
|
542
484
|
type: "integer"
|
|
543
485
|
},
|
|
544
|
-
checks_by_scope: {
|
|
545
|
-
additionalProperties: {
|
|
546
|
-
items: {
|
|
547
|
-
type: "string"
|
|
548
|
-
},
|
|
549
|
-
type: "array"
|
|
550
|
-
},
|
|
551
|
-
title: "Checks By Scope",
|
|
552
|
-
type: "object"
|
|
553
|
-
},
|
|
554
486
|
checks_by_level: {
|
|
555
487
|
additionalProperties: {
|
|
556
488
|
items: {
|
|
@@ -582,9 +514,9 @@ var cyvest_schema_default = {
|
|
|
582
514
|
title: "Threat Intel By Level",
|
|
583
515
|
type: "object"
|
|
584
516
|
},
|
|
585
|
-
|
|
517
|
+
total_tags: {
|
|
586
518
|
minimum: 0,
|
|
587
|
-
title: "Total
|
|
519
|
+
title: "Total Tags",
|
|
588
520
|
type: "integer"
|
|
589
521
|
}
|
|
590
522
|
},
|
|
@@ -596,11 +528,57 @@ var cyvest_schema_default = {
|
|
|
596
528
|
"total_checks",
|
|
597
529
|
"applied_checks",
|
|
598
530
|
"total_threat_intel",
|
|
599
|
-
"
|
|
531
|
+
"total_tags"
|
|
600
532
|
],
|
|
601
533
|
title: "StatisticsSchema",
|
|
602
534
|
type: "object"
|
|
603
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
|
+
},
|
|
604
582
|
Taxonomy: {
|
|
605
583
|
additionalProperties: false,
|
|
606
584
|
description: "Represents a structured taxonomy entry for threat intelligence.",
|
|
@@ -754,12 +732,9 @@ var cyvest_schema_default = {
|
|
|
754
732
|
},
|
|
755
733
|
checks: {
|
|
756
734
|
additionalProperties: {
|
|
757
|
-
|
|
758
|
-
$ref: "#/$defs/Check"
|
|
759
|
-
},
|
|
760
|
-
type: "array"
|
|
735
|
+
$ref: "#/$defs/Check"
|
|
761
736
|
},
|
|
762
|
-
description: "Checks
|
|
737
|
+
description: "Checks keyed by their unique key.",
|
|
763
738
|
title: "Checks",
|
|
764
739
|
type: "object"
|
|
765
740
|
},
|
|
@@ -779,12 +754,12 @@ var cyvest_schema_default = {
|
|
|
779
754
|
title: "Enrichments",
|
|
780
755
|
type: "object"
|
|
781
756
|
},
|
|
782
|
-
|
|
757
|
+
tags: {
|
|
783
758
|
additionalProperties: {
|
|
784
|
-
$ref: "#/$defs/
|
|
759
|
+
$ref: "#/$defs/Tag"
|
|
785
760
|
},
|
|
786
|
-
description: "
|
|
787
|
-
title: "
|
|
761
|
+
description: "Tags keyed by their unique key.",
|
|
762
|
+
title: "Tags",
|
|
788
763
|
type: "object"
|
|
789
764
|
},
|
|
790
765
|
stats: {
|
|
@@ -812,7 +787,7 @@ var cyvest_schema_default = {
|
|
|
812
787
|
"checks",
|
|
813
788
|
"threat_intels",
|
|
814
789
|
"enrichments",
|
|
815
|
-
"
|
|
790
|
+
"tags",
|
|
816
791
|
"stats",
|
|
817
792
|
"data_extraction",
|
|
818
793
|
"score_display"
|
|
@@ -862,10 +837,9 @@ function generateObservableKey(obsType, value) {
|
|
|
862
837
|
const normalizedValue = normalizeValue(value);
|
|
863
838
|
return `obs:${normalizedType}:${normalizedValue}`;
|
|
864
839
|
}
|
|
865
|
-
function generateCheckKey(
|
|
866
|
-
const
|
|
867
|
-
|
|
868
|
-
return `chk:${normalizedId}:${normalizedScope}`;
|
|
840
|
+
function generateCheckKey(checkName) {
|
|
841
|
+
const normalizedName = normalizeValue(checkName);
|
|
842
|
+
return `chk:${normalizedName}`;
|
|
869
843
|
}
|
|
870
844
|
function generateThreatIntelKey(source, observableKey) {
|
|
871
845
|
const normalizedSource = normalizeValue(source);
|
|
@@ -879,15 +853,32 @@ function generateEnrichmentKey(name, context) {
|
|
|
879
853
|
}
|
|
880
854
|
return `enr:${normalizedName}`;
|
|
881
855
|
}
|
|
882
|
-
function
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
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 + ":");
|
|
886
877
|
}
|
|
887
878
|
function parseKeyType(key) {
|
|
888
879
|
if (key.includes(":")) {
|
|
889
880
|
const prefix = key.split(":", 1)[0];
|
|
890
|
-
if (["obs", "chk", "ti", "enr", "
|
|
881
|
+
if (["obs", "chk", "ti", "enr", "tag"].includes(prefix)) {
|
|
891
882
|
return prefix;
|
|
892
883
|
}
|
|
893
884
|
}
|
|
@@ -925,10 +916,9 @@ function parseCheckKey(key) {
|
|
|
925
916
|
return null;
|
|
926
917
|
}
|
|
927
918
|
const parts = key.split(":");
|
|
928
|
-
if (parts.length >=
|
|
919
|
+
if (parts.length >= 2) {
|
|
929
920
|
return {
|
|
930
|
-
|
|
931
|
-
scope: parts.slice(2).join(":")
|
|
921
|
+
checkName: parts.slice(1).join(":")
|
|
932
922
|
};
|
|
933
923
|
}
|
|
934
924
|
return null;
|
|
@@ -1045,10 +1035,10 @@ function hasLevel(obj) {
|
|
|
1045
1035
|
return typeof obj === "object" && obj !== null && "level" in obj && typeof obj.level === "string" && isValidLevel(obj.level);
|
|
1046
1036
|
}
|
|
1047
1037
|
function getEntityLevel(entity) {
|
|
1048
|
-
if ("
|
|
1049
|
-
const
|
|
1050
|
-
if (typeof
|
|
1051
|
-
return
|
|
1038
|
+
if ("direct_level" in entity) {
|
|
1039
|
+
const directLevel = entity.direct_level;
|
|
1040
|
+
if (typeof directLevel === "string" && isValidLevel(directLevel)) {
|
|
1041
|
+
return directLevel;
|
|
1052
1042
|
}
|
|
1053
1043
|
}
|
|
1054
1044
|
if ("level" in entity && isValidLevel(entity.level)) {
|
|
@@ -1071,40 +1061,24 @@ function getObservableByTypeValue(inv, type, value) {
|
|
|
1071
1061
|
}
|
|
1072
1062
|
return void 0;
|
|
1073
1063
|
}
|
|
1074
|
-
function
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
return check;
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1064
|
+
function getRootObservable(inv) {
|
|
1065
|
+
const rootType = inv.data_extraction.root_type;
|
|
1066
|
+
if (!rootType) {
|
|
1067
|
+
return void 0;
|
|
1081
1068
|
}
|
|
1082
|
-
|
|
1069
|
+
const rootKey = generateObservableKey(rootType, "root");
|
|
1070
|
+
return inv.observables[rootKey];
|
|
1083
1071
|
}
|
|
1084
|
-
function
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
);
|
|
1092
|
-
}
|
|
1093
|
-
for (const checks of Object.values(inv.checks)) {
|
|
1094
|
-
for (const check of checks) {
|
|
1095
|
-
if (check.check_id.toLowerCase() === normalizedId && check.scope.toLowerCase() === normalizedScope) {
|
|
1096
|
-
return check;
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
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];
|
|
1101
1079
|
}
|
|
1102
1080
|
function getAllChecks(inv) {
|
|
1103
|
-
|
|
1104
|
-
for (const checks of Object.values(inv.checks)) {
|
|
1105
|
-
result.push(...checks);
|
|
1106
|
-
}
|
|
1107
|
-
return result;
|
|
1081
|
+
return Object.values(inv.checks);
|
|
1108
1082
|
}
|
|
1109
1083
|
function getThreatIntel(inv, key) {
|
|
1110
1084
|
return inv.threat_intels[key];
|
|
@@ -1136,46 +1110,16 @@ function getEnrichmentByName(inv, name) {
|
|
|
1136
1110
|
function getAllEnrichments(inv) {
|
|
1137
1111
|
return Object.values(inv.enrichments);
|
|
1138
1112
|
}
|
|
1139
|
-
function
|
|
1140
|
-
|
|
1141
|
-
return inv.containers[key];
|
|
1142
|
-
}
|
|
1143
|
-
function searchSubContainers(containers) {
|
|
1144
|
-
for (const container of Object.values(containers)) {
|
|
1145
|
-
if (container.key === key) {
|
|
1146
|
-
return container;
|
|
1147
|
-
}
|
|
1148
|
-
const found = searchSubContainers(container.sub_containers);
|
|
1149
|
-
if (found) return found;
|
|
1150
|
-
}
|
|
1151
|
-
return void 0;
|
|
1152
|
-
}
|
|
1153
|
-
return searchSubContainers(inv.containers);
|
|
1154
|
-
}
|
|
1155
|
-
function getContainerByPath(inv, path) {
|
|
1156
|
-
const normalizedPath = path.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "").toLowerCase();
|
|
1157
|
-
function searchContainers(containers) {
|
|
1158
|
-
for (const container of Object.values(containers)) {
|
|
1159
|
-
if (container.path.toLowerCase() === normalizedPath) {
|
|
1160
|
-
return container;
|
|
1161
|
-
}
|
|
1162
|
-
const found = searchContainers(container.sub_containers);
|
|
1163
|
-
if (found) return found;
|
|
1164
|
-
}
|
|
1165
|
-
return void 0;
|
|
1166
|
-
}
|
|
1167
|
-
return searchContainers(inv.containers);
|
|
1113
|
+
function getTag(inv, key) {
|
|
1114
|
+
return inv.tags[key];
|
|
1168
1115
|
}
|
|
1169
|
-
function
|
|
1170
|
-
const
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
}
|
|
1177
|
-
collectContainers(inv.containers);
|
|
1178
|
-
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);
|
|
1179
1123
|
}
|
|
1180
1124
|
function getAllObservables(inv) {
|
|
1181
1125
|
return Object.values(inv.observables);
|
|
@@ -1195,7 +1139,7 @@ function getCounts(inv) {
|
|
|
1195
1139
|
checks: getAllChecks(inv).length,
|
|
1196
1140
|
threatIntels: Object.keys(inv.threat_intels).length,
|
|
1197
1141
|
enrichments: Object.keys(inv.enrichments).length,
|
|
1198
|
-
|
|
1142
|
+
tags: getAllTags(inv).length,
|
|
1199
1143
|
whitelists: inv.whitelists.length
|
|
1200
1144
|
};
|
|
1201
1145
|
}
|
|
@@ -1205,6 +1149,28 @@ function getStartedAt(inv) {
|
|
|
1205
1149
|
);
|
|
1206
1150
|
return event?.timestamp;
|
|
1207
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
|
+
}
|
|
1208
1174
|
|
|
1209
1175
|
// src/finders.ts
|
|
1210
1176
|
function findObservablesByType(inv, type) {
|
|
@@ -1252,51 +1218,19 @@ function findObservablesWithThreatIntel(inv) {
|
|
|
1252
1218
|
(obs) => obs.threat_intels.length > 0
|
|
1253
1219
|
);
|
|
1254
1220
|
}
|
|
1255
|
-
function findChecksByScope(inv, scope) {
|
|
1256
|
-
const normalizedScope = scope.trim().toLowerCase();
|
|
1257
|
-
if (inv.checks[scope]) {
|
|
1258
|
-
return inv.checks[scope];
|
|
1259
|
-
}
|
|
1260
|
-
for (const [key, checks] of Object.entries(inv.checks)) {
|
|
1261
|
-
if (key.toLowerCase() === normalizedScope) {
|
|
1262
|
-
return checks;
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
return [];
|
|
1266
|
-
}
|
|
1267
1221
|
function findChecksByLevel(inv, level) {
|
|
1268
|
-
|
|
1269
|
-
for (const checks of Object.values(inv.checks)) {
|
|
1270
|
-
for (const check of checks) {
|
|
1271
|
-
if (check.level === level) {
|
|
1272
|
-
result.push(check);
|
|
1273
|
-
}
|
|
1274
|
-
}
|
|
1275
|
-
}
|
|
1276
|
-
return result;
|
|
1222
|
+
return Object.values(inv.checks).filter((check) => check.level === level);
|
|
1277
1223
|
}
|
|
1278
1224
|
function findChecksAtLeast(inv, minLevel2) {
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
if (isLevelAtLeast(check.level, minLevel2)) {
|
|
1283
|
-
result.push(check);
|
|
1284
|
-
}
|
|
1285
|
-
}
|
|
1286
|
-
}
|
|
1287
|
-
return result;
|
|
1225
|
+
return Object.values(inv.checks).filter(
|
|
1226
|
+
(check) => isLevelAtLeast(check.level, minLevel2)
|
|
1227
|
+
);
|
|
1288
1228
|
}
|
|
1289
|
-
function
|
|
1290
|
-
const
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
if (check.check_id.toLowerCase() === normalizedId) {
|
|
1295
|
-
result.push(check);
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
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
|
+
);
|
|
1300
1234
|
}
|
|
1301
1235
|
function findThreatIntelBySource(inv, source) {
|
|
1302
1236
|
const normalizedSource = source.trim().toLowerCase();
|
|
@@ -1312,52 +1246,31 @@ function findThreatIntelAtLeast(inv, minLevel2) {
|
|
|
1312
1246
|
(ti) => isLevelAtLeast(ti.level, minLevel2)
|
|
1313
1247
|
);
|
|
1314
1248
|
}
|
|
1315
|
-
function
|
|
1316
|
-
|
|
1317
|
-
function searchContainers(containers) {
|
|
1318
|
-
for (const container of Object.values(containers)) {
|
|
1319
|
-
if (container.aggregated_level === level) {
|
|
1320
|
-
result.push(container);
|
|
1321
|
-
}
|
|
1322
|
-
searchContainers(container.sub_containers);
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
|
-
searchContainers(inv.containers);
|
|
1326
|
-
return result;
|
|
1249
|
+
function findTagsByLevel(inv, level) {
|
|
1250
|
+
return Object.values(inv.tags).filter((tag) => tag.direct_level === level);
|
|
1327
1251
|
}
|
|
1328
|
-
function
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
if (isLevelAtLeast(container.aggregated_level, minLevel2)) {
|
|
1333
|
-
result.push(container);
|
|
1334
|
-
}
|
|
1335
|
-
searchContainers(container.sub_containers);
|
|
1336
|
-
}
|
|
1337
|
-
}
|
|
1338
|
-
searchContainers(inv.containers);
|
|
1339
|
-
return result;
|
|
1252
|
+
function findTagsAtLeast(inv, minLevel2) {
|
|
1253
|
+
return Object.values(inv.tags).filter(
|
|
1254
|
+
(tag) => isLevelAtLeast(tag.direct_level, minLevel2)
|
|
1255
|
+
);
|
|
1340
1256
|
}
|
|
1341
|
-
function
|
|
1257
|
+
function findTagsByNamePattern(inv, pattern) {
|
|
1258
|
+
return Object.values(inv.tags).filter((tag) => pattern.test(tag.name));
|
|
1259
|
+
}
|
|
1260
|
+
function findChecksForObservable(inv, observableKey) {
|
|
1342
1261
|
const result = [];
|
|
1343
1262
|
const seen = /* @__PURE__ */ new Set();
|
|
1344
|
-
const checkLookup = /* @__PURE__ */ new Map();
|
|
1345
|
-
for (const checks of Object.values(inv.checks)) {
|
|
1346
|
-
for (const check of checks) {
|
|
1347
|
-
checkLookup.set(check.key, check);
|
|
1348
|
-
}
|
|
1349
|
-
}
|
|
1350
1263
|
const observable = inv.observables[observableKey];
|
|
1351
1264
|
if (observable) {
|
|
1352
1265
|
for (const checkKey of observable.check_links) {
|
|
1353
|
-
const check =
|
|
1266
|
+
const check = inv.checks[checkKey];
|
|
1354
1267
|
if (check && !seen.has(check.key)) {
|
|
1355
1268
|
result.push(check);
|
|
1356
1269
|
seen.add(check.key);
|
|
1357
1270
|
}
|
|
1358
1271
|
}
|
|
1359
1272
|
}
|
|
1360
|
-
for (const check of
|
|
1273
|
+
for (const check of Object.values(inv.checks)) {
|
|
1361
1274
|
if (seen.has(check.key)) {
|
|
1362
1275
|
continue;
|
|
1363
1276
|
}
|
|
@@ -1368,7 +1281,7 @@ function getChecksForObservable(inv, observableKey) {
|
|
|
1368
1281
|
}
|
|
1369
1282
|
return result;
|
|
1370
1283
|
}
|
|
1371
|
-
function
|
|
1284
|
+
function findThreatIntelsForObservable(inv, observableKey) {
|
|
1372
1285
|
const observable = inv.observables[observableKey];
|
|
1373
1286
|
if (observable) {
|
|
1374
1287
|
return observable.threat_intels.map((tiKey) => inv.threat_intels[tiKey]).filter((ti) => ti !== void 0);
|
|
@@ -1377,51 +1290,41 @@ function getThreatIntelsForObservable(inv, observableKey) {
|
|
|
1377
1290
|
(ti) => ti.observable_key === observableKey
|
|
1378
1291
|
);
|
|
1379
1292
|
}
|
|
1380
|
-
function
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
keys.add(link.observable_key);
|
|
1387
|
-
}
|
|
1388
|
-
return Array.from(keys).map((obsKey) => inv.observables[obsKey]).filter((obs) => obs !== void 0);
|
|
1389
|
-
}
|
|
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);
|
|
1390
1299
|
}
|
|
1300
|
+
return Array.from(keys).map((obsKey) => inv.observables[obsKey]).filter((obs) => obs !== void 0);
|
|
1391
1301
|
}
|
|
1392
1302
|
return [];
|
|
1393
1303
|
}
|
|
1394
|
-
function
|
|
1304
|
+
function findChecksForTag(inv, tagKey, recursive = false) {
|
|
1395
1305
|
const result = [];
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
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);
|
|
1403
1314
|
}
|
|
1404
|
-
return void 0;
|
|
1405
1315
|
}
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
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) {
|
|
1411
1323
|
result.push(check);
|
|
1412
1324
|
}
|
|
1413
1325
|
}
|
|
1414
1326
|
}
|
|
1415
1327
|
}
|
|
1416
|
-
if (recursive) {
|
|
1417
|
-
for (const subContainer of Object.values(container2.sub_containers)) {
|
|
1418
|
-
collectChecks(subContainer);
|
|
1419
|
-
}
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
|
-
const container = findContainer(inv.containers);
|
|
1423
|
-
if (container) {
|
|
1424
|
-
collectChecks(container);
|
|
1425
1328
|
}
|
|
1426
1329
|
return result;
|
|
1427
1330
|
}
|
|
@@ -1441,29 +1344,25 @@ function sortChecksByLevel(checks) {
|
|
|
1441
1344
|
(a, b) => LEVEL_VALUES[b.level] - LEVEL_VALUES[a.level]
|
|
1442
1345
|
);
|
|
1443
1346
|
}
|
|
1444
|
-
function
|
|
1347
|
+
function findHighestScoringObservables(inv, n = 10) {
|
|
1445
1348
|
return sortObservablesByScore(Object.values(inv.observables)).slice(0, n);
|
|
1446
1349
|
}
|
|
1447
|
-
function
|
|
1448
|
-
|
|
1449
|
-
for (const checks of Object.values(inv.checks)) {
|
|
1450
|
-
allChecks.push(...checks);
|
|
1451
|
-
}
|
|
1452
|
-
return sortChecksByScore(allChecks).slice(0, n);
|
|
1350
|
+
function findHighestScoringChecks(inv, n = 10) {
|
|
1351
|
+
return sortChecksByScore(Object.values(inv.checks)).slice(0, n);
|
|
1453
1352
|
}
|
|
1454
|
-
function
|
|
1353
|
+
function findMaliciousObservables(inv) {
|
|
1455
1354
|
return findObservablesByLevel(inv, "MALICIOUS");
|
|
1456
1355
|
}
|
|
1457
|
-
function
|
|
1356
|
+
function findSuspiciousObservables(inv) {
|
|
1458
1357
|
return findObservablesByLevel(inv, "SUSPICIOUS");
|
|
1459
1358
|
}
|
|
1460
|
-
function
|
|
1359
|
+
function findMaliciousChecks(inv) {
|
|
1461
1360
|
return findChecksByLevel(inv, "MALICIOUS");
|
|
1462
1361
|
}
|
|
1463
|
-
function
|
|
1362
|
+
function findSuspiciousChecks(inv) {
|
|
1464
1363
|
return findChecksByLevel(inv, "SUSPICIOUS");
|
|
1465
1364
|
}
|
|
1466
|
-
function
|
|
1365
|
+
function getAllCheckKeys(inv) {
|
|
1467
1366
|
return Object.keys(inv.checks);
|
|
1468
1367
|
}
|
|
1469
1368
|
function getAllObservableTypes(inv) {
|
|
@@ -1600,7 +1499,7 @@ function getObservableGraph(inv) {
|
|
|
1600
1499
|
}
|
|
1601
1500
|
return { nodes, edges };
|
|
1602
1501
|
}
|
|
1603
|
-
function
|
|
1502
|
+
function findSourceObservables(inv) {
|
|
1604
1503
|
const targetKeys = /* @__PURE__ */ new Set();
|
|
1605
1504
|
for (const obs of Object.values(inv.observables)) {
|
|
1606
1505
|
for (const rel of obs.relationships) {
|
|
@@ -1748,85 +1647,93 @@ export {
|
|
|
1748
1647
|
areConnected,
|
|
1749
1648
|
compareLevels,
|
|
1750
1649
|
countRelationshipsByType,
|
|
1650
|
+
findCheckByName,
|
|
1751
1651
|
findChecksAtLeast,
|
|
1752
|
-
findChecksByCheckId,
|
|
1753
1652
|
findChecksByLevel,
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
findContainersByLevel,
|
|
1653
|
+
findChecksForObservable,
|
|
1654
|
+
findChecksForTag,
|
|
1757
1655
|
findExternalObservables,
|
|
1656
|
+
findHighestScoringChecks,
|
|
1657
|
+
findHighestScoringObservables,
|
|
1758
1658
|
findInternalObservables,
|
|
1759
1659
|
findLeafObservables,
|
|
1660
|
+
findMaliciousChecks,
|
|
1661
|
+
findMaliciousObservables,
|
|
1760
1662
|
findObservablesAtLeast,
|
|
1761
1663
|
findObservablesByLevel,
|
|
1762
1664
|
findObservablesByType,
|
|
1763
1665
|
findObservablesByValue,
|
|
1764
1666
|
findObservablesContaining,
|
|
1667
|
+
findObservablesForCheck,
|
|
1765
1668
|
findObservablesMatching,
|
|
1766
1669
|
findObservablesWithThreatIntel,
|
|
1767
1670
|
findOrphanObservables,
|
|
1768
1671
|
findPath,
|
|
1769
|
-
|
|
1672
|
+
findSourceObservables,
|
|
1673
|
+
findSuspiciousChecks,
|
|
1674
|
+
findSuspiciousObservables,
|
|
1675
|
+
findTagsAtLeast,
|
|
1676
|
+
findTagsByLevel,
|
|
1677
|
+
findTagsByNamePattern,
|
|
1770
1678
|
findThreatIntelAtLeast,
|
|
1771
1679
|
findThreatIntelByLevel,
|
|
1772
1680
|
findThreatIntelBySource,
|
|
1681
|
+
findThreatIntelsForObservable,
|
|
1773
1682
|
findWhitelistedObservables,
|
|
1774
1683
|
generateCheckKey,
|
|
1775
|
-
generateContainerKey,
|
|
1776
1684
|
generateEnrichmentKey,
|
|
1777
1685
|
generateObservableKey,
|
|
1686
|
+
generateTagKey,
|
|
1778
1687
|
generateThreatIntelKey,
|
|
1688
|
+
getAllCheckKeys,
|
|
1779
1689
|
getAllChecks,
|
|
1780
|
-
getAllContainers,
|
|
1781
1690
|
getAllEnrichments,
|
|
1782
1691
|
getAllObservableTypes,
|
|
1783
1692
|
getAllObservables,
|
|
1784
1693
|
getAllRelationshipTypes,
|
|
1785
|
-
|
|
1694
|
+
getAllTags,
|
|
1786
1695
|
getAllThreatIntelSources,
|
|
1787
1696
|
getAllThreatIntels,
|
|
1788
1697
|
getCheck,
|
|
1789
|
-
|
|
1790
|
-
getChecksForContainer,
|
|
1791
|
-
getChecksForObservable,
|
|
1698
|
+
getCheckByName,
|
|
1792
1699
|
getColorForLevel,
|
|
1793
1700
|
getColorForScore,
|
|
1794
|
-
getContainer,
|
|
1795
|
-
getContainerByPath,
|
|
1796
1701
|
getCounts,
|
|
1797
1702
|
getDataExtraction,
|
|
1798
1703
|
getEnrichment,
|
|
1799
1704
|
getEnrichmentByName,
|
|
1800
1705
|
getEntityLevel,
|
|
1801
|
-
getHighestScoringChecks,
|
|
1802
|
-
getHighestScoringObservables,
|
|
1803
1706
|
getLevelFromScore,
|
|
1804
|
-
getMaliciousChecks,
|
|
1805
|
-
getMaliciousObservables,
|
|
1806
1707
|
getObservable,
|
|
1807
1708
|
getObservableByTypeValue,
|
|
1808
1709
|
getObservableChildren,
|
|
1809
1710
|
getObservableGraph,
|
|
1810
1711
|
getObservableParents,
|
|
1811
|
-
getObservablesForCheck,
|
|
1812
1712
|
getReachableObservables,
|
|
1813
1713
|
getRelatedObservables,
|
|
1814
1714
|
getRelatedObservablesByDirection,
|
|
1815
1715
|
getRelatedObservablesByType,
|
|
1816
1716
|
getRelationshipsForObservable,
|
|
1717
|
+
getRootObservable,
|
|
1817
1718
|
getStartedAt,
|
|
1818
1719
|
getStats,
|
|
1819
|
-
|
|
1820
|
-
|
|
1720
|
+
getTag,
|
|
1721
|
+
getTagAggregatedLevel,
|
|
1722
|
+
getTagAggregatedScore,
|
|
1723
|
+
getTagAncestors,
|
|
1724
|
+
getTagByName,
|
|
1725
|
+
getTagChildren,
|
|
1726
|
+
getTagDescendants,
|
|
1821
1727
|
getThreatIntel,
|
|
1822
1728
|
getThreatIntelBySourceObservable,
|
|
1823
|
-
getThreatIntelsForObservable,
|
|
1824
1729
|
getWhitelists,
|
|
1825
1730
|
hasLevel,
|
|
1826
1731
|
isCyvest,
|
|
1827
1732
|
isLevelAtLeast,
|
|
1828
1733
|
isLevelHigherThan,
|
|
1829
1734
|
isLevelLowerThan,
|
|
1735
|
+
isTagChildOf,
|
|
1736
|
+
isTagDescendantOf,
|
|
1830
1737
|
isValidLevel,
|
|
1831
1738
|
maxLevel,
|
|
1832
1739
|
minLevel,
|