Skip to content
This repository was archived by the owner on Dec 5, 2025. It is now read-only.

Commit e59f95c

Browse files
committed
[client] Introduce fields product on software and first_seen_active on vulnerability (#941)
1 parent 1236fcd commit e59f95c

File tree

4 files changed

+71
-0
lines changed

4 files changed

+71
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# coding: utf-8
2+
import datetime
3+
4+
from pycti import OpenCTIApiClient
5+
6+
# Variables
7+
api_url = "http://opencti:4000"
8+
api_token = "bfa014e0-e02e-4aa6-a42b-603b19dcf159"
9+
10+
# OpenCTI initialization
11+
opencti_api_client = OpenCTIApiClient(api_url, api_token)
12+
13+
# Create the Intrusion Set
14+
opencti_api_client.intrusion_set.create(
15+
name="APT28",
16+
description="Evil hackers",
17+
first_seen=datetime.date.today().strftime("%Y-%m-%dT%H:%M:%S+00:00"),
18+
last_seen=datetime.date.today().strftime("%Y-%m-%dT%H:%M:%S+00:00"),
19+
update=True,
20+
)
21+
22+
# Get the intrusion set APT28
23+
intrusion_set = opencti_api_client.intrusion_set.read(
24+
filters={
25+
"mode": "and",
26+
"filters": [{"key": "name", "values": ["APT28"]}],
27+
"filterGroups": [],
28+
}
29+
)
30+
31+
# Get the relations from APT28 to malwares
32+
stix_relations = opencti_api_client.stix_core_relationship.list(
33+
fromId=intrusion_set["id"], toTypes=["Malware"]
34+
)
35+
36+
# Print
37+
for stix_relation in stix_relations:
38+
print("[" + stix_relation["to"]["stix_id"] + "] " + stix_relation["to"]["name"])

pycti/entities/opencti_stix_cyber_observable.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,18 @@ def create(self, **kwargs):
809809
),
810810
}
811811
elif type == "Software":
812+
if (
813+
"x_opencti_product" not in observable_data
814+
and self.opencti.get_attribute_in_extension(
815+
"x_opencti_product", observable_data
816+
)
817+
is not None
818+
):
819+
observable_data["x_opencti_product"] = (
820+
self.opencti.get_attribute_in_extension(
821+
"x_opencti_product", observable_data
822+
)
823+
)
812824
input_variables["Software"] = {
813825
"name": (
814826
observable_data["name"] if "name" in observable_data else None
@@ -832,6 +844,11 @@ def create(self, **kwargs):
832844
if "version" in observable_data
833845
else None
834846
),
847+
"x_opencti_product": (
848+
observable_data["x_opencti_product"]
849+
if "x_opencti_product" in observable_data
850+
else None
851+
),
835852
}
836853
elif type == "Url":
837854
input_variables["Url"] = {

pycti/entities/opencti_vulnerability.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ def __init__(self, opencti):
150150
x_opencti_cvss_v4_availability_impact_s
151151
x_opencti_cvss_v4_exploit_maturity
152152
x_opencti_cwe
153+
x_opencti_first_seen_active
153154
x_opencti_cisa_kev
154155
x_opencti_epss_score
155156
x_opencti_epss_percentile
@@ -452,6 +453,7 @@ def create(self, **kwargs):
452453
x_opencti_epss_score = kwargs.get("x_opencti_epss_score", None)
453454
x_opencti_epss_percentile = kwargs.get("x_opencti_epss_percentile", None)
454455
x_opencti_score = kwargs.get("x_opencti_score", None)
456+
x_opencti_first_seen_active = kwargs.get("x_opencti_first_seen_active", None)
455457
x_opencti_stix_ids = kwargs.get("x_opencti_stix_ids", None)
456458
granted_refs = kwargs.get("objectOrganization", None)
457459
x_opencti_workflow_id = kwargs.get("x_opencti_workflow_id", None)
@@ -538,6 +540,7 @@ def create(self, **kwargs):
538540
"x_opencti_epss_score": x_opencti_epss_score,
539541
"x_opencti_epss_percentile": x_opencti_epss_percentile,
540542
"x_opencti_score": x_opencti_score,
543+
"x_opencti_first_seen_active": x_opencti_first_seen_active,
541544
"x_opencti_stix_ids": x_opencti_stix_ids,
542545
"x_opencti_workflow_id": x_opencti_workflow_id,
543546
"update": update,
@@ -867,6 +870,12 @@ def import_from_stix2(self, **kwargs):
867870
stix_object["x_opencti_score"] = (
868871
self.opencti.get_attribute_in_extension("score", stix_object)
869872
)
873+
if "x_opencti_first_seen_active" not in stix_object:
874+
stix_object["x_opencti_first_seen_active"] = (
875+
self.opencti.get_attribute_in_extension(
876+
"first_seen_active", stix_object
877+
)
878+
)
870879

871880
return self.create(
872881
stix_id=stix_object["id"],
@@ -1158,6 +1167,11 @@ def import_from_stix2(self, **kwargs):
11581167
if "x_opencti_score" in stix_object
11591168
else None
11601169
),
1170+
x_opencti_first_seen_active=(
1171+
stix_object["x_opencti_first_seen_active"]
1172+
if "x_opencti_first_seen_active" in stix_object
1173+
else None
1174+
),
11611175
update=update,
11621176
)
11631177
else:

pycti/entities/stix_cyber_observable/opencti_stix_cyber_observable_properties.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@
215215
languages
216216
vendor
217217
version
218+
x_opencti_product
218219
}
219220
... on Url {
220221
value
@@ -519,6 +520,7 @@
519520
languages
520521
vendor
521522
version
523+
x_opencti_product
522524
}
523525
... on Url {
524526
value

0 commit comments

Comments
 (0)