assemblyline-v4-service 4.5.0.27__py3-none-any.whl → 4.5.0.29__py3-none-any.whl

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.

Potentially problematic release.


This version of assemblyline-v4-service might be problematic. Click here for more details.

@@ -1 +1 @@
1
- 4.5.0.27
1
+ 4.5.0.29
@@ -88,6 +88,7 @@ class Task:
88
88
  def _add_file(self, path: str, name: str, description: str,
89
89
  classification: Optional[Classification] = None,
90
90
  is_section_image: bool = False,
91
+ is_supplementary: bool = False,
91
92
  allow_dynamic_recursion: bool = False,
92
93
  parent_relation: str = PARENT_RELATION.EXTRACTED) -> Optional[Dict[str, str]]:
93
94
  # Reject empty files
@@ -112,6 +113,7 @@ class Task:
112
113
  classification=self._classification.max_classification(self.min_classification, classification),
113
114
  path=path,
114
115
  is_section_image=is_section_image,
116
+ is_supplementary=is_supplementary,
115
117
  allow_dynamic_recursion=allow_dynamic_recursion,
116
118
  parent_relation=parent_relation
117
119
  )
@@ -173,9 +175,8 @@ class Task:
173
175
  if not description:
174
176
  raise ValueError("Description cannot be empty")
175
177
 
176
- file = self._add_file(
177
- path, name, description, classification, is_section_image, parent_relation=parent_relation
178
- )
178
+ file = self._add_file(path, name, description, classification, is_section_image,
179
+ is_supplementary=True, parent_relation=parent_relation)
179
180
 
180
181
  if not file:
181
182
  return None
@@ -261,6 +261,7 @@ class RunPrivilegedService(ServerBase):
261
261
  file_info['classification'],
262
262
  task.ttl,
263
263
  file_info.get('is_section_image', False),
264
+ file_info.get('is_supplementary', False),
264
265
  expected_sha256=file_info['sha256']
265
266
  )
266
267
 
@@ -320,11 +320,20 @@ class ServiceUpdater(ThreadedCoreBase):
320
320
 
321
321
  if self._service.update_config.generates_signatures:
322
322
  output_directory = tempfile.mkdtemp(prefix="update_dir_", dir=UPDATER_DIR)
323
+ sources_removed_locally = False
324
+ if self._update_dir:
325
+ current_update_dir = os.path.join(self._update_dir, self.updater_type)
323
326
 
324
- # Check if new signatures have been added
327
+ if os.path.exists(current_update_dir):
328
+ sources_removed_locally = set(os.listdir(current_update_dir)) - \
329
+ set([s.name for s in self._service.update_config.sources])
330
+
331
+
332
+ # Check if new signatures have been added (or it there's been a local change since the last update)
325
333
  self.log.info("Check for new signatures.")
326
- if self.client.signature.update_available(since=epoch_to_iso(old_update_time) or None,
327
- sig_type=self.updater_type):
334
+ if sources_removed_locally or \
335
+ self.client.signature.update_available(since=epoch_to_iso(old_update_time) or None,
336
+ sig_type=self.updater_type):
328
337
  self.log.info("An update is available for download from the datastore")
329
338
 
330
339
  self.log.debug(f"{self.updater_type} update available since {epoch_to_iso(old_update_time) or ''}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: assemblyline-v4-service
3
- Version: 4.5.0.27
3
+ Version: 4.5.0.29
4
4
  Summary: Assemblyline 4 - Service base
5
5
  Home-page: https://github.com/CybercentreCanada/assemblyline-v4-service/
6
6
  Author: CCCS Assemblyline development team
@@ -1,8 +1,8 @@
1
- assemblyline_v4_service/VERSION,sha256=p2Vdvfc45LvNQUDOPwM_x-SO5DzFjpjGpf4vWn6HGic,9
1
+ assemblyline_v4_service/VERSION,sha256=5iHmLzWZaCCho1OVr_tp40DbE-FbtCYT4q-9Dc1CJeY,9
2
2
  assemblyline_v4_service/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  assemblyline_v4_service/healthz.py,sha256=3QGBg0EZuXC6UN411HFwpLNEop9UvS9feFhvBUTP-k4,1576
4
4
  assemblyline_v4_service/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- assemblyline_v4_service/run_privileged_service.py,sha256=qd4DmHo5G_Tpv8tb0A96qNfCGuXBu5MlIKB205z5e5w,14514
5
+ assemblyline_v4_service/run_privileged_service.py,sha256=ipCjdB_PZXt85Hmu9r9q7QjKXI8Y6iF-w6Aa4PMn9S4,14576
6
6
  assemblyline_v4_service/run_service.py,sha256=NiFX52NfsbBQY6E3nrjoB3e2XxIlwFcQpYYY-rADIk4,5996
7
7
  assemblyline_v4_service/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  assemblyline_v4_service/common/api.py,sha256=Xzp8j4HCCfjPvNSGKiZl5ttH2_Itg47cjlH0NXNtth0,6849
@@ -12,7 +12,7 @@ assemblyline_v4_service/common/ocr.py,sha256=3fV0PyY3oui_ucAM9dkolP0VRYKACKJuGY4
12
12
  assemblyline_v4_service/common/ontology_helper.py,sha256=QpwerYoS5hXjWzpx3Pmwv6j2330PQVYqxYGamjcpW3I,7890
13
13
  assemblyline_v4_service/common/request.py,sha256=ZP80rDWIyVotwVDN70L7ujN9RoxZRdmaeUN0DFIvrT4,11732
14
14
  assemblyline_v4_service/common/result.py,sha256=9AqM6qCYiia_Bpyn_fBFhzNQMcqJbtFSiGjp57fXW2E,32713
15
- assemblyline_v4_service/common/task.py,sha256=7yNvXk5B27QookJNp4-Y1iGhV8LfhLDaYWzF-uFGWgo,13576
15
+ assemblyline_v4_service/common/task.py,sha256=xX771hC3vkjRtnR4MjPh_26ZmAkQ_jceuu6U7BSFMd8,13704
16
16
  assemblyline_v4_service/common/utils.py,sha256=k2__d-V5LjB6o2IKbjVe7tJWKcKuUHto5TyT5oKhIa0,3890
17
17
  assemblyline_v4_service/dev/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  assemblyline_v4_service/dev/run_service_once.py,sha256=caqUHYc27JLuJPOwkEuhf8-wlaYPvzDrRqfEuhMMxqw,10455
@@ -22,7 +22,7 @@ assemblyline_v4_service/updater/app.py,sha256=Mtmx4bkXfP4nFqqa5q15jW8QIXr4JK84lC
22
22
  assemblyline_v4_service/updater/client.py,sha256=oOOIzh-Q-b5uOTo3C4rVSfQxqUO5Y_ogDmUhvWfm5uo,9518
23
23
  assemblyline_v4_service/updater/gunicorn_config.py,sha256=p3j2KPBeD5jvMw9O5i7vAtlRgPSVVxIG9AO0DfN82J8,1247
24
24
  assemblyline_v4_service/updater/helper.py,sha256=-B35wdjpeY4t1R9SPDrTFHFKHwE3uzy9N69mV6mHy-g,9532
25
- assemblyline_v4_service/updater/updater.py,sha256=5cJH82VTP3VrwoNE97ubKP2dr90AI_T-AKRistvN5rI,29013
25
+ assemblyline_v4_service/updater/updater.py,sha256=6LFvqBkNu6mDaBKZGEaFGtE8g3DtDNBYWt8jXx6fnOw,29507
26
26
  test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  test/conftest.py,sha256=W3SieQpZsZpGEmtLqY4aIlxREDSsHceyCrFcFsWUM0U,1851
28
28
  test/test_healthz.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
@@ -34,12 +34,12 @@ test/test_common/test_base.py,sha256=fuJSSlPxIDHq6HU1xbvaMFitw2z1spOZNHD2SJ4UUic
34
34
  test/test_common/test_helper.py,sha256=sO6YAiBhKTqaxlpLhFYDuy2ZdbuF2cg07Ylzo83ZzQs,2575
35
35
  test/test_common/test_ocr.py,sha256=mt_PgElgwQKJmNrp2nRVx9NjfMedVk40I6IV317vATI,1753
36
36
  test/test_common/test_ontology_helper.py,sha256=KhHEBg_ecJyQbDw79NMT4FzUyA4C1Aak3HEQCwBfM2s,7914
37
- test/test_common/test_request.py,sha256=VzWw-NZKTRIXKwCACIT2SSHE70HMZ3IeBk1AJiT-cjU,11472
38
- test/test_common/test_result.py,sha256=0WK_Zfw7e6IJl5nTSUUt6LFTvbu6cVynaTOdpuYkBvg,42559
39
- test/test_common/test_task.py,sha256=RWsGEN0L-xKoRAsGv2x4JZcSAySS9aBF4dwL9t7tepo,18668
37
+ test/test_common/test_request.py,sha256=zoBURe3QbycWK4I7uvkixcmykrOCqY_TchmxJinNXjU,11822
38
+ test/test_common/test_result.py,sha256=6BiOKxEPrKBjOY44jv3TY-yiXm0qI1ok_CZBnjP9TM4,45447
39
+ test/test_common/test_task.py,sha256=LzEIfFHJEcB_YPucOZGtm1TwyHnqJE-0Qc2MDsH4TN4,18957
40
40
  test/test_common/test_utils.py,sha256=TbnBxqpS_ZC5ptXR9XJX3xtbItD0mTbtiBxxdyP8J5k,5904
41
- assemblyline_v4_service-4.5.0.27.dist-info/LICENCE.md,sha256=NSkYo9EH8h5oOkzg4VhjAHF4339MqPP2cQ8msTPgl-c,1396
42
- assemblyline_v4_service-4.5.0.27.dist-info/METADATA,sha256=Z_bZhozIN3PH4RyjQ2DdrD3IjPCGJ0iNQdWde8sb-Ag,9495
43
- assemblyline_v4_service-4.5.0.27.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
44
- assemblyline_v4_service-4.5.0.27.dist-info/top_level.txt,sha256=LpTOEaVCatkrvbVq3EZseMSIa2PQZU-2rhuO_FTpZgY,29
45
- assemblyline_v4_service-4.5.0.27.dist-info/RECORD,,
41
+ assemblyline_v4_service-4.5.0.29.dist-info/LICENCE.md,sha256=NSkYo9EH8h5oOkzg4VhjAHF4339MqPP2cQ8msTPgl-c,1396
42
+ assemblyline_v4_service-4.5.0.29.dist-info/METADATA,sha256=qtnn26Vo3FLqi9Jkp8SWsXVGQOQ6sYiz_KuJSnjzlVo,9495
43
+ assemblyline_v4_service-4.5.0.29.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
44
+ assemblyline_v4_service-4.5.0.29.dist-info/top_level.txt,sha256=LpTOEaVCatkrvbVq3EZseMSIa2PQZU-2rhuO_FTpZgY,29
45
+ assemblyline_v4_service-4.5.0.29.dist-info/RECORD,,
@@ -13,6 +13,7 @@ from assemblyline.odm.messages.task import Task as ServiceTask
13
13
  # Ensure service manifest is instantiated before importing from OCR submodule
14
14
  setup_module()
15
15
 
16
+
16
17
  @pytest.fixture
17
18
  def service_request():
18
19
  st = ServiceTask({
@@ -71,11 +72,12 @@ def test_add_extracted(service_request):
71
72
  'classification': 'TLP:C',
72
73
  'description': 'description',
73
74
  'is_section_image': False,
75
+ 'is_supplementary': False,
74
76
  'name': 'name',
75
77
  'parent_relation': 'EXTRACTED',
76
78
  'path': path,
77
79
  'sha256': '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'
78
- },
80
+ },
79
81
  ]
80
82
 
81
83
  # Raise MaxExtractedExceeded
@@ -97,17 +99,20 @@ def test_add_extracted(service_request):
97
99
  'classification': 'TLP:C',
98
100
  'description': 'description',
99
101
  'is_section_image': False,
102
+ 'is_supplementary': False,
100
103
  'name': 'name',
101
104
  'parent_relation': 'DYNAMIC',
102
105
  'path': path,
103
106
  'sha256': '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'
104
- },
107
+ },
105
108
  ]
106
109
 
107
110
 
108
111
  @pytest.mark.skipif(len(TESSERACT_LIST) < 1, reason="Requires tesseract-ocr apt package")
109
112
  def test_add_image(service_request):
110
- image_path = os.path.join(os.path.dirname(__file__), "b32969aa664e3905c20f865cdd7b921f922678f5c3850c78e4c803fbc1757a8e")
113
+ image_path = os.path.join(
114
+ os.path.dirname(__file__),
115
+ "b32969aa664e3905c20f865cdd7b921f922678f5c3850c78e4c803fbc1757a8e")
111
116
 
112
117
  # Basic
113
118
  assert service_request.add_image(image_path, "image_name", "description of image") == {
@@ -131,6 +136,7 @@ def test_add_image(service_request):
131
136
  'classification': 'TLP:C',
132
137
  'description': 'description of image',
133
138
  'is_section_image': True,
139
+ 'is_supplementary': True,
134
140
  'name': 'image_name',
135
141
  'parent_relation': 'INFORMATION',
136
142
  'sha256': '09bf99ab5431af13b701a06dc2b04520aea9fd346584fa2a034d6d4af0c57329'
@@ -140,6 +146,7 @@ def test_add_image(service_request):
140
146
  'classification': 'TLP:C',
141
147
  'description': 'description of image (thumbnail)',
142
148
  'is_section_image': True,
149
+ 'is_supplementary': True,
143
150
  'name': 'image_name.thumb',
144
151
  'parent_relation': 'INFORMATION',
145
152
  'sha256': '1af0e0d99845493b64cf402b3704170f17ecf15001714016e48f9d4854218901'
@@ -152,7 +159,8 @@ def test_add_image(service_request):
152
159
  ocr_heuristic_id = 1
153
160
  _, path = tempfile.mkstemp()
154
161
  ocr_io = open(path, "w")
155
- data = service_request.add_image(image_path, "image_name", "description of image", "TLP:A", ocr_heuristic_id, ocr_io)
162
+ data = service_request.add_image(image_path, "image_name", "description of image",
163
+ "TLP:A", ocr_heuristic_id, ocr_io)
156
164
  assert data["img"] == {
157
165
  'description': 'description of image',
158
166
  'name': 'image_name',
@@ -188,17 +196,23 @@ def test_add_image(service_request):
188
196
 
189
197
  heur_dict = get_heuristic_primitives(data["ocr_section"].__dict__["_heuristic"])
190
198
 
191
- assert heur_dict == {'heur_id': 1, 'score': 1200, 'attack_ids': ['T1005'], 'signatures': {'ransomware_strings': 8}, 'frequency': 0, 'score_map': {}}
199
+ assert heur_dict == {
200
+ 'heur_id': 1, 'score': 1200, 'attack_ids': ['T1005'],
201
+ 'signatures': {'ransomware_strings': 8},
202
+ 'frequency': 0, 'score_map': {}}
192
203
 
193
204
  assert service_request.temp_submission_data == {}
194
205
 
195
206
  service_request.task.supplementary.clear()
196
207
 
197
208
  # Classification, OCR heuristic, OCR_IO, image with password
198
- image_path = os.path.join(os.path.dirname(__file__), "4031ed8786439eee24b87f84901e38038a76b8c55e9d87dd5a7d88df2806c1cf")
209
+ image_path = os.path.join(
210
+ os.path.dirname(__file__),
211
+ "4031ed8786439eee24b87f84901e38038a76b8c55e9d87dd5a7d88df2806c1cf")
199
212
  _, path = tempfile.mkstemp()
200
213
  ocr_io = open(path, "w")
201
- data = service_request.add_image(image_path, "image_name", "description of image", "TLP:A", ocr_heuristic_id, ocr_io)
214
+ data = service_request.add_image(image_path, "image_name", "description of image",
215
+ "TLP:A", ocr_heuristic_id, ocr_io)
202
216
  assert data["img"] == {
203
217
  'description': 'description of image',
204
218
  'name': 'image_name',
@@ -217,9 +231,12 @@ def test_add_image(service_request):
217
231
 
218
232
  heur_dict = get_heuristic_primitives(data["ocr_section"].__dict__["_heuristic"])
219
233
 
220
- assert heur_dict == {'heur_id': 1, 'score': 250, 'attack_ids': ['T1005'], 'signatures': {'password_strings': 1}, 'frequency': 0, 'score_map': {}}
234
+ assert heur_dict == {
235
+ 'heur_id': 1, 'score': 250, 'attack_ids': ['T1005'],
236
+ 'signatures': {'password_strings': 1},
237
+ 'frequency': 0, 'score_map': {}}
221
238
 
222
- assert service_request.temp_submission_data == {'passwords':[' 975', '975', 'DOCUMENT', 'PASSWORD', 'PASSWORD:']}
239
+ assert service_request.temp_submission_data == {'passwords': [' 975', '975', 'DOCUMENT', 'PASSWORD', 'PASSWORD:']}
223
240
 
224
241
 
225
242
  def test_add_supplementary(service_request):
@@ -239,11 +256,12 @@ def test_add_supplementary(service_request):
239
256
  'classification': 'TLP:C',
240
257
  'description': 'description',
241
258
  'is_section_image': False,
259
+ 'is_supplementary': True,
242
260
  'name': 'name',
243
261
  'parent_relation': 'INFORMATION',
244
262
  'path': path,
245
263
  'sha256': '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'
246
- },
264
+ },
247
265
  ]
248
266
 
249
267
 
@@ -280,7 +298,7 @@ def test_get_param(service_request):
280
298
  service_request.get_param("blah")
281
299
 
282
300
  # Submission parameter exists
283
- service_request.task.service_config = {"blah":"blah"}
301
+ service_request.task.service_config = {"blah": "blah"}
284
302
  assert service_request.get_param("blah") == "blah"
285
303
 
286
304
 
@@ -1,3 +1,15 @@
1
+ from assemblyline.odm.messages.task import Task as ServiceTask
2
+ from assemblyline_v4_service.common.task import Task
3
+ from assemblyline_v4_service.common.result import (
4
+ BODY_FORMAT, DividerSectionBody, GraphSectionBody, Heuristic, ImageSectionBody, InvalidFunctionException,
5
+ InvalidHeuristicException, JSONSectionBody, KVSectionBody, MemorydumpSectionBody, MultiSectionBody,
6
+ OrderedKVSectionBody, ProcessItem, ProcessTreeSectionBody, Result, ResultAggregationException, ResultGraphSection,
7
+ ResultImageSection, ResultJSONSection, ResultKeyValueSection, ResultMemoryDumpSection, ResultMultiSection,
8
+ ResultOrderedKeyValueSection, ResultProcessTreeSection, ResultSection, ResultTableSection, ResultTextSection,
9
+ ResultTimelineSection, ResultURLSection, SectionBody, TableRow, TableSectionBody, TextSectionBody,
10
+ TimelineSectionBody, TypeSpecificResultSection, URLSectionBody, get_heuristic_primitives)
11
+ from assemblyline_v4_service.common.request import ServiceRequest
12
+ import pytest
1
13
  import os
2
14
  import tempfile
3
15
  from test.test_common import TESSERACT_LIST, setup_module
@@ -6,13 +18,6 @@ from test.test_common import TESSERACT_LIST, setup_module
6
18
  setup_module()
7
19
 
8
20
 
9
- import pytest
10
- from assemblyline_v4_service.common.request import ServiceRequest
11
- from assemblyline_v4_service.common.result import *
12
- from assemblyline_v4_service.common.task import Task
13
-
14
- from assemblyline.odm.messages.task import Task as ServiceTask
15
-
16
21
  @pytest.fixture
17
22
  def heuristic():
18
23
  return Heuristic(1)
@@ -595,11 +600,21 @@ def test_imagesectionbody_init(service_request):
595
600
  @pytest.mark.skipif(len(TESSERACT_LIST) < 1, reason="Requires tesseract-ocr apt package")
596
601
  def test_imagesectionbody_add_image(service_request):
597
602
  isb = ImageSectionBody(service_request)
598
- image_path = os.path.join(os.path.dirname(__file__), "b32969aa664e3905c20f865cdd7b921f922678f5c3850c78e4c803fbc1757a8e")
603
+ image_path = os.path.join(
604
+ os.path.dirname(__file__),
605
+ "b32969aa664e3905c20f865cdd7b921f922678f5c3850c78e4c803fbc1757a8e")
599
606
 
600
607
  # Basic
601
608
  assert isb.add_image(image_path, "image_name", "description of image") is None
602
- assert isb._data == [{'img': {'name': 'image_name', 'sha256': '09bf99ab5431af13b701a06dc2b04520aea9fd346584fa2a034d6d4af0c57329', 'description': 'description of image'}, 'thumb': {'name': 'image_name.thumb', 'sha256': '1af0e0d99845493b64cf402b3704170f17ecf15001714016e48f9d4854218901', 'description': 'description of image (thumbnail)'}}]
609
+ assert isb._data == [
610
+ {'img': {
611
+ 'name': 'image_name',
612
+ 'sha256': '09bf99ab5431af13b701a06dc2b04520aea9fd346584fa2a034d6d4af0c57329',
613
+ 'description': 'description of image'},
614
+ 'thumb': {
615
+ 'name': 'image_name.thumb',
616
+ 'sha256': '1af0e0d99845493b64cf402b3704170f17ecf15001714016e48f9d4854218901',
617
+ 'description': 'description of image (thumbnail)'}}]
603
618
 
604
619
  isb._data.clear()
605
620
 
@@ -607,8 +622,25 @@ def test_imagesectionbody_add_image(service_request):
607
622
  ocr_heuristic_id = 1
608
623
  _, path = tempfile.mkstemp()
609
624
  ocr_io = open(path, "w")
610
- assert isb.add_image(image_path, "image_name", "description of image", "TLP:A", ocr_heuristic_id, ocr_io).body == '{"ransomware": ["YOUR FILES HAVE BEEN ENCRYPTED AND YOU WON\'T BE ABLE TO DECRYPT THEM.", "YOU CAN BUY DECRYPTION SOFTWARE FROM US, THIS SOFTWARE WILL ALLOW YOU TO RECOVER ALL OF YOUR DATA AND", "RANSOMWARE FROM YOUR COMPUTER. THE PRICE OF THE SOFTWARE IS $.2..%.. PAYMENT CAN BE MADE IN BITCOIN OR XMR.", "How 00! PAY, WHERE DO | GET BITCOIN OR XMR?", "YOURSELF TO FIND OUT HOW TO BUY BITCOIN OR XMR.", "PAYMENT INFORMATION: SEND $15, TO ONE OF OUR CRYPTO ADDRESSES, THEN SEND US EMAIL WITH PAYMENT", "CONFIRMATION AND YOU\'LL GET THE DECRYPTION SOFTWARE IN EMAIL.", "BTC ADDRESS : bciqsht77cpgw7kv420r4secmu88g34wvn96dsyc5s"]}'
611
- assert isb._data == [{'img': {'name': 'image_name', 'sha256': '09bf99ab5431af13b701a06dc2b04520aea9fd346584fa2a034d6d4af0c57329', 'description': 'description of image'}, 'thumb': {'name': 'image_name.thumb', 'sha256': '1af0e0d99845493b64cf402b3704170f17ecf15001714016e48f9d4854218901', 'description': 'description of image (thumbnail)'}}]
625
+ assert isb.add_image(image_path, "image_name", "description of image", "TLP:A", ocr_heuristic_id,
626
+ ocr_io).body == '{"ransomware": ["YOUR FILES HAVE BEEN ENCRYPTED AND YOU WON\'T BE ABLE TO ' \
627
+ 'DECRYPT THEM.", "YOU CAN BUY DECRYPTION SOFTWARE FROM US, THIS SOFTWARE ' \
628
+ 'WILL ALLOW YOU TO RECOVER ALL OF YOUR DATA AND", "RANSOMWARE FROM YOUR ' \
629
+ 'COMPUTER. THE PRICE OF THE SOFTWARE IS $.2..%.. PAYMENT CAN BE MADE IN ' \
630
+ 'BITCOIN OR XMR.", "How 00! PAY, WHERE DO | GET BITCOIN OR XMR?", "YOURSELF ' \
631
+ 'TO FIND OUT HOW TO BUY BITCOIN OR XMR.", "PAYMENT INFORMATION: SEND $15, ' \
632
+ 'TO ONE OF OUR CRYPTO ADDRESSES, THEN SEND US EMAIL WITH PAYMENT", ' \
633
+ '"CONFIRMATION AND YOU\'LL GET THE DECRYPTION SOFTWARE IN EMAIL.", ' \
634
+ '"BTC ADDRESS : bciqsht77cpgw7kv420r4secmu88g34wvn96dsyc5s"]}'
635
+ assert isb._data == [
636
+ {'img': {
637
+ 'name': 'image_name',
638
+ 'sha256': '09bf99ab5431af13b701a06dc2b04520aea9fd346584fa2a034d6d4af0c57329',
639
+ 'description': 'description of image'},
640
+ 'thumb': {
641
+ 'name': 'image_name.thumb',
642
+ 'sha256': '1af0e0d99845493b64cf402b3704170f17ecf15001714016e48f9d4854218901',
643
+ 'description': 'description of image (thumbnail)'}}]
612
644
 
613
645
 
614
646
  # Ensure that the image files added are marked as `is_image_section`
@@ -653,7 +685,8 @@ def test_timelinesectionbody_add_node():
653
685
 
654
686
  tsb.add_node("title", "content", "opposite_content")
655
687
  assert tsb._format == BODY_FORMAT.TIMELINE
656
- assert tsb._data == [{'title': 'title', 'content': 'content', 'opposite_content': 'opposite_content', 'icon': None, 'signatures': [], 'score': 0}]
688
+ assert tsb._data == [{'title': 'title', 'content': 'content',
689
+ 'opposite_content': 'opposite_content', 'icon': None, 'signatures': [], 'score': 0}]
657
690
 
658
691
 
659
692
  def test_resultsection_init():
@@ -710,7 +743,8 @@ def test_resultsection_init():
710
743
  assert rs._body_format == BODY_FORMAT.GRAPH_DATA
711
744
  assert rs._body_config == {}
712
745
  assert rs.classification == 'TLP:AMBER'
713
- assert get_heuristic_primitives(rs._heuristic) == {'heur_id': 1, 'score': 250, 'attack_ids': ['T1005'], 'signatures': {}, 'frequency': 1, 'score_map': {}}
746
+ assert get_heuristic_primitives(rs._heuristic) == {'heur_id': 1, 'score': 250, 'attack_ids': [
747
+ 'T1005'], 'signatures': {}, 'frequency': 1, 'score_map': {}}
714
748
  assert rs._tags == {"a": "b"}
715
749
  assert rs.zeroize_on_tag_safe is True
716
750
  assert rs.auto_collapse is True
@@ -939,14 +973,16 @@ def test_resultsection_set_heuristic():
939
973
 
940
974
  # Pass int heuristic
941
975
  assert rs.set_heuristic(1) is None
942
- assert get_heuristic_primitives(rs._heuristic) == {'heur_id': 1, 'score': 250, 'attack_ids': ['T1005'], 'signatures': {}, 'frequency': 1, 'score_map': {}}
976
+ assert get_heuristic_primitives(rs._heuristic) == {'heur_id': 1, 'score': 250, 'attack_ids': [
977
+ 'T1005'], 'signatures': {}, 'frequency': 1, 'score_map': {}}
943
978
 
944
979
  rs._heuristic = None
945
980
 
946
981
  # Pass Heuristic heuristic
947
982
  heur = Heuristic(1)
948
983
  assert rs.set_heuristic(heur) is None
949
- assert get_heuristic_primitives(rs._heuristic) == {'heur_id': 1, 'score': 250, 'attack_ids': ['T1005'], 'signatures': {}, 'frequency': 1, 'score_map': {}}
984
+ assert get_heuristic_primitives(rs._heuristic) == {'heur_id': 1, 'score': 250, 'attack_ids': [
985
+ 'T1005'], 'signatures': {}, 'frequency': 1, 'score_map': {}}
950
986
 
951
987
  # Try adding a heuristic again
952
988
  with pytest.raises(InvalidHeuristicException):
@@ -957,13 +993,21 @@ def test_resultsection_set_heuristic():
957
993
  # Set the Heuristic heuristic with attack ID and signature
958
994
  heur = Heuristic(1)
959
995
  assert rs.set_heuristic(heur, attack_id="T1001", signature="blah") is None
960
- assert get_heuristic_primitives(rs._heuristic) == {'heur_id': 1, 'score': 250, 'attack_ids': ['T1005', 'T1001'], 'signatures': {"blah": 1}, 'frequency': 1, 'score_map': {}}
996
+ assert get_heuristic_primitives(
997
+ rs._heuristic) == {
998
+ 'heur_id': 1, 'score': 250, 'attack_ids': ['T1005', 'T1001'],
999
+ 'signatures': {"blah": 1},
1000
+ 'frequency': 1, 'score_map': {}}
961
1001
 
962
1002
  rs._heuristic = None
963
1003
 
964
1004
  # Set the int heuristic with attack ID and signature
965
1005
  assert rs.set_heuristic(1, attack_id="T1001", signature="blah") is None
966
- assert get_heuristic_primitives(rs._heuristic) == {'heur_id': 1, 'score': 250, 'attack_ids': ['T1005', 'T1001'], 'signatures': {"blah": 1}, 'frequency': 1, 'score_map': {}}
1006
+ assert get_heuristic_primitives(
1007
+ rs._heuristic) == {
1008
+ 'heur_id': 1, 'score': 250, 'attack_ids': ['T1005', 'T1001'],
1009
+ 'signatures': {"blah": 1},
1010
+ 'frequency': 1, 'score_map': {}}
967
1011
 
968
1012
 
969
1013
  def test_resultsection_set_tags():
@@ -1241,7 +1285,15 @@ def test_resultimagesection_add_image(service_request):
1241
1285
 
1242
1286
  # Basic
1243
1287
  assert ris.add_image(image_path, "image_name", "description of image") is None
1244
- assert ris.section_body._data == [{'img': {'name': 'image_name', 'sha256': '09bf99ab5431af13b701a06dc2b04520aea9fd346584fa2a034d6d4af0c57329', 'description': 'description of image'}, 'thumb': {'name': 'image_name.thumb', 'sha256': '1af0e0d99845493b64cf402b3704170f17ecf15001714016e48f9d4854218901', 'description': 'description of image (thumbnail)'}}]
1288
+ assert ris.section_body._data == [{
1289
+ 'img':
1290
+ {'name': 'image_name',
1291
+ 'sha256': '09bf99ab5431af13b701a06dc2b04520aea9fd346584fa2a034d6d4af0c57329',
1292
+ 'description': 'description of image'},
1293
+ 'thumb':
1294
+ {'name': 'image_name.thumb',
1295
+ 'sha256': '1af0e0d99845493b64cf402b3704170f17ecf15001714016e48f9d4854218901',
1296
+ 'description': 'description of image (thumbnail)'}}]
1245
1297
 
1246
1298
  ris = ResultImageSection(service_request, "title_text_as_str")
1247
1299
 
@@ -1250,8 +1302,15 @@ def test_resultimagesection_add_image(service_request):
1250
1302
  _, path = tempfile.mkstemp()
1251
1303
  ocr_io = open(path, "w")
1252
1304
  assert ris.add_image(image_path, "image_name", "description of image", "TLP:A", ocr_heuristic_id, ocr_io) is None
1253
- assert ris.section_body._data == [{'img': {'name': 'image_name', 'sha256': '09bf99ab5431af13b701a06dc2b04520aea9fd346584fa2a034d6d4af0c57329', 'description': 'description of image'}, 'thumb': {'name': 'image_name.thumb', 'sha256': '1af0e0d99845493b64cf402b3704170f17ecf15001714016e48f9d4854218901', 'description': 'description of image (thumbnail)'}}]
1254
-
1305
+ assert ris.section_body._data == [{
1306
+ 'img':
1307
+ {'name': 'image_name',
1308
+ 'sha256': '09bf99ab5431af13b701a06dc2b04520aea9fd346584fa2a034d6d4af0c57329',
1309
+ 'description': 'description of image'},
1310
+ 'thumb':
1311
+ {'name': 'image_name.thumb',
1312
+ 'sha256': '1af0e0d99845493b64cf402b3704170f17ecf15001714016e48f9d4854218901',
1313
+ 'description': 'description of image (thumbnail)'}}]
1255
1314
 
1256
1315
  ris = ResultImageSection(service_request, "title_text_as_str")
1257
1316
 
@@ -1259,8 +1318,28 @@ def test_resultimagesection_add_image(service_request):
1259
1318
  ocr_heuristic_id = 1
1260
1319
  _, path = tempfile.mkstemp()
1261
1320
  ocr_io = open(path, "w")
1262
- assert ris.add_image(image_path, "image_name", "description of image", "TLP:A", ocr_heuristic_id, ocr_io, auto_add_ocr_section=False).body == '{"ransomware": ["YOUR FILES HAVE BEEN ENCRYPTED AND YOU WON\'T BE ABLE TO DECRYPT THEM.", "YOU CAN BUY DECRYPTION SOFTWARE FROM US, THIS SOFTWARE WILL ALLOW YOU TO RECOVER ALL OF YOUR DATA AND", "RANSOMWARE FROM YOUR COMPUTER. THE PRICE OF THE SOFTWARE IS $.2..%.. PAYMENT CAN BE MADE IN BITCOIN OR XMR.", "How 00! PAY, WHERE DO | GET BITCOIN OR XMR?", "YOURSELF TO FIND OUT HOW TO BUY BITCOIN OR XMR.", "PAYMENT INFORMATION: SEND $15, TO ONE OF OUR CRYPTO ADDRESSES, THEN SEND US EMAIL WITH PAYMENT", "CONFIRMATION AND YOU\'LL GET THE DECRYPTION SOFTWARE IN EMAIL.", "BTC ADDRESS : bciqsht77cpgw7kv420r4secmu88g34wvn96dsyc5s"]}'
1263
- assert ris.section_body._data == [{'img': {'name': 'image_name', 'sha256': '09bf99ab5431af13b701a06dc2b04520aea9fd346584fa2a034d6d4af0c57329', 'description': 'description of image'}, 'thumb': {'name': 'image_name.thumb', 'sha256': '1af0e0d99845493b64cf402b3704170f17ecf15001714016e48f9d4854218901', 'description': 'description of image (thumbnail)'}}]
1321
+ assert ris.add_image(image_path, "image_name", "description of image", "TLP:A", ocr_heuristic_id, ocr_io,
1322
+ auto_add_ocr_section=False).body == '{"ransomware": ["YOUR FILES HAVE BEEN ENCRYPTED AND ' \
1323
+ 'YOU WON\'T BE ABLE TO DECRYPT THEM.", "YOU CAN BUY ' \
1324
+ 'DECRYPTION SOFTWARE FROM US, THIS SOFTWARE WILL ALLOW ' \
1325
+ 'YOU TO RECOVER ALL OF YOUR DATA AND", "RANSOMWARE FROM ' \
1326
+ 'YOUR COMPUTER. THE PRICE OF THE SOFTWARE IS $.2..%.. ' \
1327
+ 'PAYMENT CAN BE MADE IN BITCOIN OR XMR.", "How 00! PAY, ' \
1328
+ 'WHERE DO | GET BITCOIN OR XMR?", "YOURSELF TO FIND OUT ' \
1329
+ 'HOW TO BUY BITCOIN OR XMR.", "PAYMENT INFORMATION: ' \
1330
+ 'SEND $15, TO ONE OF OUR CRYPTO ADDRESSES, THEN SEND ' \
1331
+ 'US EMAIL WITH PAYMENT", "CONFIRMATION AND YOU\'LL GET ' \
1332
+ 'THE DECRYPTION SOFTWARE IN EMAIL.", "BTC ADDRESS : ' \
1333
+ 'bciqsht77cpgw7kv420r4secmu88g34wvn96dsyc5s"]}'
1334
+ assert ris.section_body._data == [{
1335
+ 'img': {
1336
+ 'name': 'image_name',
1337
+ 'sha256': '09bf99ab5431af13b701a06dc2b04520aea9fd346584fa2a034d6d4af0c57329',
1338
+ 'description': 'description of image'},
1339
+ 'thumb': {
1340
+ 'name': 'image_name.thumb',
1341
+ 'sha256': '1af0e0d99845493b64cf402b3704170f17ecf15001714016e48f9d4854218901',
1342
+ 'description': 'description of image (thumbnail)'}}]
1264
1343
 
1265
1344
  # Ensure that the image files added are marked as `is_image_section`
1266
1345
  image_hashes = [img['sha256'] for img in ris.section_body._data[0].values()]
@@ -1281,7 +1360,9 @@ def test_resulttimelinesection_add_node():
1281
1360
 
1282
1361
  rts.add_node("title", "content", "opposite_content")
1283
1362
  assert rts.body_format == BODY_FORMAT.TIMELINE
1284
- assert rts.section_body._data == [{'title': 'title', 'content': 'content', 'opposite_content': 'opposite_content', 'icon': None, 'signatures': [], 'score': 0}]
1363
+ assert rts.section_body._data == [
1364
+ {'title': 'title', 'content': 'content',
1365
+ 'opposite_content': 'opposite_content', 'icon': None, 'signatures': [], 'score': 0}]
1285
1366
 
1286
1367
 
1287
1368
  def test_resultmultisection_init():
@@ -6,7 +6,7 @@ from logging import Logger
6
6
  import pytest
7
7
  from assemblyline_v4_service.common import helper
8
8
  from assemblyline_v4_service.common.result import ResultSection
9
- from assemblyline_v4_service.common.task import *
9
+ from assemblyline_v4_service.common.task import Task, Classification, MaxExtractedExceeded, ServiceAPI, Result
10
10
 
11
11
  from assemblyline.odm.messages.task import DataItem, TagItem
12
12
  from assemblyline.odm.messages.task import Task as ServiceTask
@@ -160,6 +160,7 @@ def test_task_add_file(servicetask):
160
160
  "classification": "TLP:C",
161
161
  "path": path,
162
162
  "is_section_image": False,
163
+ 'is_supplementary': False,
163
164
  "allow_dynamic_recursion": False,
164
165
  "parent_relation": "EXTRACTED",
165
166
  }
@@ -174,6 +175,7 @@ def test_task_add_file(servicetask):
174
175
  "classification": "TLP:C",
175
176
  "path": path,
176
177
  "is_section_image": False,
178
+ 'is_supplementary': False,
177
179
  "allow_dynamic_recursion": True,
178
180
  "parent_relation": "DYNAMIC",
179
181
  }
@@ -211,7 +213,7 @@ def test_task_add_extracted(servicetask, mocker):
211
213
  # Safelisted file hash
212
214
  service_attributes = helper.get_service_attributes()
213
215
  sa = ServiceAPI(service_attributes, None)
214
- with mocker.patch.object(sa, "lookup_safelist", return_value={"enabled": True, "type": "file"}) as m:
216
+ with mocker.patch.object(sa, "lookup_safelist", return_value={"enabled": True, "type": "file"}) as _:
215
217
  t.safelist_config.enabled = True
216
218
  assert t.add_extracted(path, "name", "description", safelist_interface=sa) is False
217
219
 
@@ -225,6 +227,7 @@ def test_task_add_extracted(servicetask, mocker):
225
227
  "classification": "TLP:C",
226
228
  "path": path,
227
229
  "is_section_image": False,
230
+ 'is_supplementary': False,
228
231
  "allow_dynamic_recursion": False,
229
232
  "parent_relation": "EXTRACTED",
230
233
  }
@@ -260,6 +263,7 @@ def test_task_add_supplementary(servicetask):
260
263
  "classification": "TLP:C",
261
264
  "path": path,
262
265
  "is_section_image": False,
266
+ 'is_supplementary': True,
263
267
  "allow_dynamic_recursion": False,
264
268
  "parent_relation": "INFORMATION",
265
269
  }
@@ -271,6 +275,7 @@ def test_task_add_supplementary(servicetask):
271
275
  "classification": "TLP:C",
272
276
  "path": path,
273
277
  "is_section_image": False,
278
+ 'is_supplementary': True,
274
279
  "allow_dynamic_recursion": False,
275
280
  "parent_relation": "INFORMATION",
276
281
  }
@@ -405,6 +410,7 @@ def test_task_get_service_result(servicetask):
405
410
  "classification": "TLP:C",
406
411
  "description": "description",
407
412
  "is_section_image": False,
413
+ "is_supplementary": False,
408
414
  "name": "name",
409
415
  "parent_relation": "EXTRACTED",
410
416
  "path": path,