@cyvest/cyvest-js 3.2.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -45,7 +45,6 @@ __export(index_exports, {
45
45
  findExternalObservables: () => findExternalObservables,
46
46
  findInternalObservables: () => findInternalObservables,
47
47
  findLeafObservables: () => findLeafObservables,
48
- findManuallyScored: () => findManuallyScored,
49
48
  findObservablesAtLeast: () => findObservablesAtLeast,
50
49
  findObservablesByLevel: () => findObservablesByLevel,
51
50
  findObservablesByType: () => findObservablesByType,
@@ -104,7 +103,6 @@ __export(index_exports, {
104
103
  getRelatedObservablesByType: () => getRelatedObservablesByType,
105
104
  getRelationshipsForObservable: () => getRelationshipsForObservable,
106
105
  getStats: () => getStats,
107
- getStatsChecks: () => getStatsChecks,
108
106
  getSuspiciousChecks: () => getSuspiciousChecks,
109
107
  getSuspiciousObservables: () => getSuspiciousObservables,
110
108
  getThreatIntel: () => getThreatIntel,
@@ -140,6 +138,97 @@ var import_ajv_formats = __toESM(require("ajv-formats"));
140
138
  // ../../../schema/cyvest.schema.json
141
139
  var cyvest_schema_default = {
142
140
  $defs: {
141
+ AuditEvent: {
142
+ additionalProperties: true,
143
+ description: "Centralized audit event for investigation-level changes.",
144
+ properties: {
145
+ event_id: {
146
+ title: "Event Id",
147
+ type: "string"
148
+ },
149
+ timestamp: {
150
+ format: "date-time",
151
+ title: "Timestamp",
152
+ type: "string"
153
+ },
154
+ event_type: {
155
+ title: "Event Type",
156
+ type: "string"
157
+ },
158
+ actor: {
159
+ anyOf: [
160
+ {
161
+ type: "string"
162
+ },
163
+ {
164
+ type: "null"
165
+ }
166
+ ],
167
+ default: null,
168
+ title: "Actor"
169
+ },
170
+ reason: {
171
+ anyOf: [
172
+ {
173
+ type: "string"
174
+ },
175
+ {
176
+ type: "null"
177
+ }
178
+ ],
179
+ default: null,
180
+ title: "Reason"
181
+ },
182
+ tool: {
183
+ anyOf: [
184
+ {
185
+ type: "string"
186
+ },
187
+ {
188
+ type: "null"
189
+ }
190
+ ],
191
+ default: null,
192
+ title: "Tool"
193
+ },
194
+ object_type: {
195
+ anyOf: [
196
+ {
197
+ type: "string"
198
+ },
199
+ {
200
+ type: "null"
201
+ }
202
+ ],
203
+ default: null,
204
+ title: "Object Type"
205
+ },
206
+ object_key: {
207
+ anyOf: [
208
+ {
209
+ type: "string"
210
+ },
211
+ {
212
+ type: "null"
213
+ }
214
+ ],
215
+ default: null,
216
+ title: "Object Key"
217
+ },
218
+ details: {
219
+ additionalProperties: true,
220
+ title: "Details",
221
+ type: "object"
222
+ }
223
+ },
224
+ required: [
225
+ "event_id",
226
+ "timestamp",
227
+ "event_type"
228
+ ],
229
+ title: "AuditEvent",
230
+ type: "object"
231
+ },
143
232
  Check: {
144
233
  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.",
145
234
  properties: {
@@ -171,17 +260,17 @@ var cyvest_schema_default = {
171
260
  level: {
172
261
  $ref: "#/$defs/Level"
173
262
  },
174
- observables: {
263
+ origin_investigation_id: {
264
+ title: "Origin Investigation Id",
265
+ type: "string"
266
+ },
267
+ observable_links: {
175
268
  items: {
176
- type: "string"
269
+ $ref: "#/$defs/ObservableLink"
177
270
  },
178
- title: "Observables",
271
+ title: "Observable Links",
179
272
  type: "array"
180
273
  },
181
- score_policy: {
182
- $ref: "#/$defs/CheckScorePolicy",
183
- default: "auto"
184
- },
185
274
  key: {
186
275
  title: "Key",
187
276
  type: "string"
@@ -200,22 +289,14 @@ var cyvest_schema_default = {
200
289
  "extra",
201
290
  "score",
202
291
  "level",
203
- "observables",
292
+ "origin_investigation_id",
293
+ "observable_links",
204
294
  "key",
205
295
  "score_display"
206
296
  ],
207
297
  title: "Check",
208
298
  type: "object"
209
299
  },
210
- CheckScorePolicy: {
211
- description: "Controls how a check reacts to linked observables.",
212
- enum: [
213
- "auto",
214
- "manual"
215
- ],
216
- title: "CheckScorePolicy",
217
- type: "string"
218
- },
219
300
  Container: {
220
301
  additionalProperties: false,
221
302
  description: "Groups checks and sub-containers for hierarchical organization.\n\nContainers allow structuring the investigation into logical sections\nwith aggregated scores and levels.",
@@ -276,6 +357,10 @@ var cyvest_schema_default = {
276
357
  root_type: {
277
358
  anyOf: [
278
359
  {
360
+ enum: [
361
+ "file",
362
+ "artifact"
363
+ ],
279
364
  type: "string"
280
365
  },
281
366
  {
@@ -286,13 +371,13 @@ var cyvest_schema_default = {
286
371
  description: "Root observable type used during data extraction.",
287
372
  title: "Root Type"
288
373
  },
289
- score_mode: {
374
+ score_mode_obs: {
290
375
  $ref: "#/$defs/ScoreMode",
291
- description: "Score aggregation mode: 'max' takes highest score, 'sum' adds all scores."
376
+ description: "Observable score aggregation mode: 'max' takes highest score, 'sum' adds all scores."
292
377
  }
293
378
  },
294
379
  required: [
295
- "score_mode"
380
+ "score_mode_obs"
296
381
  ],
297
382
  title: "DataExtractionSchema",
298
383
  type: "object"
@@ -425,13 +510,13 @@ var cyvest_schema_default = {
425
510
  title: "Key",
426
511
  type: "string"
427
512
  },
428
- generated_by_checks: {
429
- description: "Checks that generated this observable.",
513
+ check_links: {
514
+ description: "Checks that currently link to this observable (navigation-only).",
430
515
  items: {
431
516
  type: "string"
432
517
  },
433
518
  readOnly: true,
434
- title: "Generated By Checks",
519
+ title: "Check Links",
435
520
  type: "array"
436
521
  },
437
522
  score_display: {
@@ -452,12 +537,40 @@ var cyvest_schema_default = {
452
537
  "threat_intels",
453
538
  "relationships",
454
539
  "key",
455
- "generated_by_checks",
540
+ "check_links",
456
541
  "score_display"
457
542
  ],
458
543
  title: "Observable",
459
544
  type: "object"
460
545
  },
546
+ ObservableLink: {
547
+ additionalProperties: false,
548
+ description: "Edge metadata for a Check\u2194Observable association.",
549
+ properties: {
550
+ observable_key: {
551
+ title: "Observable Key",
552
+ type: "string"
553
+ },
554
+ propagation_mode: {
555
+ $ref: "#/$defs/PropagationMode",
556
+ default: "LOCAL_ONLY"
557
+ }
558
+ },
559
+ required: [
560
+ "observable_key"
561
+ ],
562
+ title: "ObservableLink",
563
+ type: "object"
564
+ },
565
+ PropagationMode: {
566
+ description: "Controls how a Check\u2194Observable link propagates across merged investigations.",
567
+ enum: [
568
+ "LOCAL_ONLY",
569
+ "GLOBAL"
570
+ ],
571
+ title: "PropagationMode",
572
+ type: "string"
573
+ },
461
574
  Relationship: {
462
575
  description: "Represents a relationship between observables.",
463
576
  properties: {
@@ -617,28 +730,6 @@ var cyvest_schema_default = {
617
730
  title: "StatisticsSchema",
618
731
  type: "object"
619
732
  },
620
- StatsChecksSchema: {
621
- additionalProperties: false,
622
- description: "Schema for check statistics summary.",
623
- properties: {
624
- checks: {
625
- minimum: 0,
626
- title: "Checks",
627
- type: "integer"
628
- },
629
- applied: {
630
- minimum: 0,
631
- title: "Applied",
632
- type: "integer"
633
- }
634
- },
635
- required: [
636
- "checks",
637
- "applied"
638
- ],
639
- title: "StatsChecksSchema",
640
- type: "object"
641
- },
642
733
  ThreatIntel: {
643
734
  description: "Represents threat intelligence from an external source.\n\nThreat intelligence provides verdicts about observables from sources\nlike VirusTotal, URLScan.io, etc.",
644
735
  properties: {
@@ -704,6 +795,24 @@ var cyvest_schema_default = {
704
795
  additionalProperties: false,
705
796
  description: "Schema for a complete serialized investigation.\n\nThis model describes the output of `serialize_investigation()` from\n`cyvest.io_serialization`. It is the top-level schema for exported investigations.\n\nEntity types reference the runtime models directly. When generating schemas with\n`mode='serialization'`, Pydantic respects field_serializer decorators and produces\nschemas matching the actual model_dump() output.",
706
797
  properties: {
798
+ investigation_id: {
799
+ description: "Stable investigation identity (ULID).",
800
+ title: "Investigation Id",
801
+ type: "string"
802
+ },
803
+ investigation_name: {
804
+ anyOf: [
805
+ {
806
+ type: "string"
807
+ },
808
+ {
809
+ type: "null"
810
+ }
811
+ ],
812
+ default: null,
813
+ description: "Optional human-readable investigation name.",
814
+ title: "Investigation Name"
815
+ },
707
816
  started_at: {
708
817
  description: "Investigation start time (UTC).",
709
818
  format: "date-time",
@@ -732,6 +841,14 @@ var cyvest_schema_default = {
732
841
  title: "Whitelists",
733
842
  type: "array"
734
843
  },
844
+ event_log: {
845
+ description: "Append-only investigation audit log.",
846
+ items: {
847
+ $ref: "#/$defs/AuditEvent"
848
+ },
849
+ title: "Event Log",
850
+ type: "array"
851
+ },
735
852
  observables: {
736
853
  additionalProperties: {
737
854
  $ref: "#/$defs/Observable"
@@ -790,10 +907,6 @@ var cyvest_schema_default = {
790
907
  $ref: "#/$defs/StatisticsSchema",
791
908
  description: "Investigation statistics summary."
792
909
  },
793
- stats_checks: {
794
- $ref: "#/$defs/StatsChecksSchema",
795
- description: "Check statistics summary."
796
- },
797
910
  data_extraction: {
798
911
  $ref: "#/$defs/DataExtractionSchema",
799
912
  description: "Data extraction metadata."
@@ -806,6 +919,7 @@ var cyvest_schema_default = {
806
919
  }
807
920
  },
808
921
  required: [
922
+ "investigation_id",
809
923
  "started_at",
810
924
  "score",
811
925
  "level",
@@ -818,7 +932,6 @@ var cyvest_schema_default = {
818
932
  "enrichments",
819
933
  "containers",
820
934
  "stats",
821
- "stats_checks",
822
935
  "data_extraction",
823
936
  "score_display"
824
937
  ],
@@ -1191,9 +1304,6 @@ function getWhitelists(inv) {
1191
1304
  function getStats(inv) {
1192
1305
  return inv.stats;
1193
1306
  }
1194
- function getStatsChecks(inv) {
1195
- return inv.stats_checks;
1196
- }
1197
1307
  function getDataExtraction(inv) {
1198
1308
  return inv.data_extraction;
1199
1309
  }
@@ -1300,17 +1410,6 @@ function findChecksByCheckId(inv, checkId) {
1300
1410
  }
1301
1411
  return result;
1302
1412
  }
1303
- function findManuallyScored(inv) {
1304
- const result = [];
1305
- for (const checks of Object.values(inv.checks)) {
1306
- for (const check of checks) {
1307
- if (check.score_policy === "manual") {
1308
- result.push(check);
1309
- }
1310
- }
1311
- }
1312
- return result;
1313
- }
1314
1413
  function findThreatIntelBySource(inv, source) {
1315
1414
  const normalizedSource = source.trim().toLowerCase();
1316
1415
  return Object.values(inv.threat_intels).filter(
@@ -1353,13 +1452,32 @@ function findContainersAtLeast(inv, minLevel2) {
1353
1452
  }
1354
1453
  function getChecksForObservable(inv, observableKey) {
1355
1454
  const result = [];
1455
+ const seen = /* @__PURE__ */ new Set();
1456
+ const checkLookup = /* @__PURE__ */ new Map();
1356
1457
  for (const checks of Object.values(inv.checks)) {
1357
1458
  for (const check of checks) {
1358
- if (check.observables.includes(observableKey)) {
1459
+ checkLookup.set(check.key, check);
1460
+ }
1461
+ }
1462
+ const observable = inv.observables[observableKey];
1463
+ if (observable) {
1464
+ for (const checkKey of observable.check_links) {
1465
+ const check = checkLookup.get(checkKey);
1466
+ if (check && !seen.has(check.key)) {
1359
1467
  result.push(check);
1468
+ seen.add(check.key);
1360
1469
  }
1361
1470
  }
1362
1471
  }
1472
+ for (const check of checkLookup.values()) {
1473
+ if (seen.has(check.key)) {
1474
+ continue;
1475
+ }
1476
+ if (check.observable_links.some((link) => link.observable_key === observableKey)) {
1477
+ result.push(check);
1478
+ seen.add(check.key);
1479
+ }
1480
+ }
1363
1481
  return result;
1364
1482
  }
1365
1483
  function getThreatIntelsForObservable(inv, observableKey) {
@@ -1375,7 +1493,11 @@ function getObservablesForCheck(inv, checkKey) {
1375
1493
  for (const checks of Object.values(inv.checks)) {
1376
1494
  for (const check of checks) {
1377
1495
  if (check.key === checkKey) {
1378
- return check.observables.map((obsKey) => inv.observables[obsKey]).filter((obs) => obs !== void 0);
1496
+ const keys = /* @__PURE__ */ new Set();
1497
+ for (const link of check.observable_links) {
1498
+ keys.add(link.observable_key);
1499
+ }
1500
+ return Array.from(keys).map((obsKey) => inv.observables[obsKey]).filter((obs) => obs !== void 0);
1379
1501
  }
1380
1502
  }
1381
1503
  }
@@ -1748,7 +1870,6 @@ function getRelationshipsForObservable(inv, observableKey) {
1748
1870
  findExternalObservables,
1749
1871
  findInternalObservables,
1750
1872
  findLeafObservables,
1751
- findManuallyScored,
1752
1873
  findObservablesAtLeast,
1753
1874
  findObservablesByLevel,
1754
1875
  findObservablesByType,
@@ -1807,7 +1928,6 @@ function getRelationshipsForObservable(inv, observableKey) {
1807
1928
  getRelatedObservablesByType,
1808
1929
  getRelationshipsForObservable,
1809
1930
  getStats,
1810
- getStatsChecks,
1811
1931
  getSuspiciousChecks,
1812
1932
  getSuspiciousObservables,
1813
1933
  getThreatIntel,