sandbox-cli 0.2.33__tar.gz → 0.2.35__tar.gz

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.
Files changed (37) hide show
  1. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/PKG-INFO +6 -6
  2. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/pyproject.toml +6 -6
  3. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/cli/downloader.py +73 -33
  4. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/cli/images.py +2 -2
  5. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/cli/scanner/__init__.py +6 -6
  6. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/internal/helpers.py +5 -4
  7. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/downloader/__init__.py +63 -52
  8. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/scanner/__init__.py +2 -2
  9. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/scanner/advanced.py +2 -2
  10. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/scanner/rescan.py +2 -2
  11. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/.gitignore +0 -0
  12. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/LICENSE +0 -0
  13. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/NOTICE +0 -0
  14. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/README.md +0 -0
  15. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/__main__.py +0 -0
  16. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/cli/__init__.py +0 -0
  17. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/cli/reporter.py +0 -0
  18. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/cli/rules/__init__.py +0 -0
  19. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/cli/unpack.py +0 -0
  20. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/console.py +0 -0
  21. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/internal/__init__.py +0 -0
  22. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/internal/config.py +0 -0
  23. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/models/__init__.py +0 -0
  24. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/models/detections.py +0 -0
  25. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/models/sandbox_arguments.py +0 -0
  26. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/__init__.py +0 -0
  27. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/compiler/__init__.py +0 -0
  28. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/compiler/abc.py +0 -0
  29. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/compiler/docker.py +0 -0
  30. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/compiler/ssh.py +0 -0
  31. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/extractors.py +0 -0
  32. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/merge_dll_hooks.py +0 -0
  33. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/unpack/__init__.py +0 -0
  34. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/unpack/plugins/__init__.py +0 -0
  35. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/unpack/plugins/abc.py +0 -0
  36. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/unpack/plugins/correlation.py +0 -0
  37. {sandbox_cli-0.2.33 → sandbox_cli-0.2.35}/sandbox_cli/utils/unpack/plugins/sort_by_plugins.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sandbox-cli
3
- Version: 0.2.33
3
+ Version: 0.2.35
4
4
  Summary: Command line tool for interaction with sandboxes
5
5
  Project-URL: Homepage, https://github.com/Security-Experts-Community/sandbox-cli
6
6
  Project-URL: Documentation, https://security-experts-community.github.io/sandbox-cli
@@ -12,13 +12,13 @@ License-File: LICENSE
12
12
  License-File: NOTICE
13
13
  Requires-Python: >=3.11
14
14
  Requires-Dist: aiofiles>=24.1.0
15
- Requires-Dist: asyncssh>=2.20.0
16
- Requires-Dist: cryptography>=44.0.2
17
- Requires-Dist: cyclopts>=3.16.0
15
+ Requires-Dist: asyncssh>=2.21.0
16
+ Requires-Dist: cryptography>=45.0.4
17
+ Requires-Dist: cyclopts>=3.22.5
18
18
  Requires-Dist: docker>=7.1.0
19
- Requires-Dist: ptsandbox>=5.0.4
19
+ Requires-Dist: ptsandbox>=5.0.6
20
20
  Requires-Dist: pyzipper>=0.3.6
21
- Requires-Dist: rich>=14.0.0
21
+ Requires-Dist: rich>=14.1.0
22
22
  Requires-Dist: zstandard>=0.23.0
23
23
  Description-Content-Type: text/markdown
24
24
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sandbox-cli"
3
- version = "0.2.33"
3
+ version = "0.2.35"
4
4
  description = "Command line tool for interaction with sandboxes"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -9,13 +9,13 @@ license-files = ["LICENSE", "NOTICE"]
9
9
  authors = [{ name = "Alexey Kolesnikov" }]
10
10
  dependencies = [
11
11
  "aiofiles>=24.1.0",
12
- "asyncssh>=2.20.0",
13
- "cryptography>=44.0.2",
14
- "cyclopts>=3.16.0",
12
+ "asyncssh>=2.21.0",
13
+ "cryptography>=45.0.4",
14
+ "cyclopts>=3.22.5",
15
15
  "docker>=7.1.0",
16
- "ptsandbox>=5.0.4",
16
+ "ptsandbox>=5.0.6",
17
17
  "pyzipper>=0.3.6",
18
- "rich>=14.0.0",
18
+ "rich>=14.1.0",
19
19
  "zstandard>=0.23.0",
20
20
  ]
21
21
 
@@ -1,4 +1,5 @@
1
1
  import asyncio
2
+ import os
2
3
  from collections.abc import Coroutine
3
4
  from http import HTTPStatus
4
5
  from pathlib import Path
@@ -9,10 +10,11 @@ from uuid import UUID
9
10
  import aiofiles
10
11
  import aiohttp
11
12
  import aiohttp.client_exceptions
13
+ import orjson
12
14
  from cyclopts import Parameter
13
15
  from ptsandbox import Sandbox
14
16
  from ptsandbox.models import Artifact, SandboxBaseTaskResponse
15
- from rich.progress import Progress, SpinnerColumn, TextColumn, TimeElapsedColumn
17
+ from rich.progress import Progress, SpinnerColumn, TaskID, TextColumn, TimeElapsedColumn
16
18
 
17
19
  from sandbox_cli.console import console
18
20
  from sandbox_cli.internal.config import settings
@@ -51,20 +53,19 @@ async def download_command(
51
53
  Parameter(
52
54
  help="Links to tasks or task ids",
53
55
  negative="",
54
- required=True,
55
56
  ),
56
- ],
57
+ ] = [],
57
58
  /,
58
59
  *,
59
60
  key: Annotated[
60
61
  str,
61
62
  Parameter(
62
63
  name=["--key", "-k"],
63
- help=f"The key to access the sandbox **{'**,**'.join(x.name for x in settings.sandbox_keys)}**",
64
+ help=f"The key to access the sandbox **{'**,**'.join(x.name.get_secret_value() for x in settings.sandbox_keys)}**",
64
65
  validator=validate_key,
65
66
  group="Sandbox",
66
67
  ),
67
- ] = settings.sandbox_keys[0].name,
68
+ ] = settings.sandbox_keys[0].name.get_secret_value(),
68
69
  out_dir: Annotated[
69
70
  Path,
70
71
  Parameter(
@@ -127,7 +128,7 @@ async def download_command(
127
128
  crashdumps: Annotated[
128
129
  bool,
129
130
  Parameter(
130
- name=["--crashdumps", "-c"],
131
+ name=["--crashdumps", "-C"],
131
132
  help="Download crashdumps (maybe be more 1GB)",
132
133
  negative="",
133
134
  group="Download options",
@@ -160,11 +161,35 @@ async def download_command(
160
161
  group="Download options",
161
162
  ),
162
163
  ] = False,
164
+ query: Annotated[
165
+ str | None,
166
+ Parameter(
167
+ name=["--query", "-q"],
168
+ help="Query for searching tasks (leave empty for last tasks)",
169
+ group="Search",
170
+ )
171
+ ] = None,
172
+ count: Annotated[
173
+ int,
174
+ Parameter(
175
+ name=["--count", "-c"],
176
+ help="How many tasks find and download",
177
+ group="Search",
178
+ )
179
+ ] = 20,
163
180
  ) -> None:
164
181
  """
165
182
  Download any artifact from the sandbox.
166
183
  """
167
184
 
185
+ progress = Progress(
186
+ SpinnerColumn(),
187
+ TextColumn("{task.description}"),
188
+ TimeElapsedColumn(),
189
+ console=console,
190
+ transient=True,
191
+ )
192
+
168
193
  async def worker(
169
194
  report: SandboxBaseTaskResponse.LongReport,
170
195
  sandbox: Sandbox,
@@ -197,39 +222,30 @@ async def download_command(
197
222
  )
198
223
 
199
224
  if unpack and out_dir.exists():
200
- Unpack(out_dir).run()
201
-
202
- progress = Progress(
203
- SpinnerColumn(),
204
- TextColumn("{task.description}"),
205
- TimeElapsedColumn(),
206
- console=console,
207
- transient=True,
208
- )
209
-
210
- tasks: list[Coroutine[Any, Any, Artifact.EngineResult | None]] = []
225
+ # multiple images can be downloaded from the task
226
+ if not (out_dir / "events-correlated.log.gz").exists():
227
+ subfolders = [f.path for f in os.scandir(out_dir) if f.is_dir()]
228
+ for folder in subfolders:
229
+ Unpack(Path(folder)).run()
230
+ else:
231
+ Unpack(out_dir).run()
211
232
 
212
- for task in tasks_id:
213
- sandbox, task_id = get_key_and_task(key, task)
214
- if not sandbox or not task_id:
215
- continue
233
+ async def create_task(sandbox: Sandbox, task_id: str) -> None:
234
+ progress_task_id = progress.add_task(description=rf"\[[green1]{task_id}[/]] fetching info", start=True)
216
235
 
217
236
  try:
218
237
  result = await sandbox.get_report(task_id=task_id)
219
238
  except aiohttp.client_exceptions.ClientResponseError as e:
220
239
  if e.status == HTTPStatus.NOT_FOUND:
221
- console.warning(
222
- f"The report cannot be accessed from {task_id}.\n"
223
- "Read more about it in: https://security-experts-community.github.io/py-ptsandbox/usage/public-api/download-files/"
224
- )
225
- continue
240
+ console.warning(f"Not found information for {task_id}")
241
+ return
226
242
 
227
243
  if (report := result.get_long_report()) is None:
228
- console.warning(
229
- f"The report cannot be accessed from {task_id}.\n"
230
- "Read more about it in: https://security-experts-community.github.io/py-ptsandbox/usage/public-api/download-files/"
231
- )
232
- continue
244
+ console.warning(f"Not found information for {task_id}")
245
+ return
246
+
247
+ progress.stop_task(task_id=progress_task_id)
248
+ progress.update(task_id=progress_task_id, visible=False)
233
249
 
234
250
  tasks.append(
235
251
  worker(
@@ -249,6 +265,30 @@ async def download_command(
249
265
  )
250
266
  )
251
267
 
268
+ tasks: list[Coroutine[Any, Any, Artifact.EngineResult | None]] = []
269
+
270
+ if query is not None:
271
+ sandbox = Sandbox(get_key_by_name(key_name=key))
272
+
273
+ limit = 40 if count > 40 else count
274
+ viewed, next_cursor = 0, ""
275
+
276
+ while viewed <= count:
277
+ response = await sandbox.get_tasks(query=query, limit=limit, next_cursor=next_cursor)
278
+
279
+ with progress:
280
+ await asyncio.gather(*(create_task(sandbox, task.id) for task in response.tasks))
281
+
282
+ viewed += limit
283
+ next_cursor = response.next_cursor
284
+
285
+ for task in tasks_id:
286
+ sandbox, task_id = get_key_and_task(key, task)
287
+ if not sandbox or not task_id:
288
+ continue
289
+
290
+ await create_task(sandbox, task_id)
291
+
252
292
  with progress:
253
293
  await asyncio.gather(*tasks)
254
294
 
@@ -273,11 +313,11 @@ def download_email(
273
313
  str,
274
314
  Parameter(
275
315
  name=["--key", "-k"],
276
- help=f"The key to access the sandbox **{'**,**'.join(x.name for x in settings.sandbox_keys)}**",
316
+ help=f"The key to access the sandbox **{'**,**'.join(x.name.get_secret_value() for x in settings.sandbox_keys)}**",
277
317
  validator=validate_key,
278
318
  group="Sandbox",
279
319
  ),
280
- ] = settings.sandbox_keys[0].name,
320
+ ] = settings.sandbox_keys[0].name.get_secret_value(),
281
321
  ) -> None:
282
322
  """
283
323
  Upload an email and get its headers.
@@ -15,11 +15,11 @@ async def get_images(
15
15
  str,
16
16
  Parameter(
17
17
  name=["--key", "-k"],
18
- help=f"The key to access the sandbox **{'**,**'.join(x.name for x in settings.sandbox_keys)}**",
18
+ help=f"The key to access the sandbox **{'**,**'.join(x.name.get_secret_value() for x in settings.sandbox_keys)}**",
19
19
  validator=validate_key,
20
20
  group="Sandbox",
21
21
  ),
22
- ] = settings.sandbox_keys[0].name,
22
+ ] = settings.sandbox_keys[0].name.get_secret_value(),
23
23
  ) -> None:
24
24
  """
25
25
  Get available images in the sandbox.
@@ -80,11 +80,11 @@ async def re_scan(
80
80
  str,
81
81
  Parameter(
82
82
  name=["--key", "-k"],
83
- help=f"The key to access the sandbox **{'**,**'.join(x.name for x in settings.sandbox_keys)}**",
83
+ help=f"The key to access the sandbox **{'**,**'.join(x.name.get_secret_value() for x in settings.sandbox_keys)}**",
84
84
  validator=validate_key,
85
85
  group="Sandbox Options",
86
86
  ),
87
- ] = settings.sandbox_keys[0].name,
87
+ ] = settings.sandbox_keys[0].name.get_secret_value(),
88
88
  is_local: Annotated[
89
89
  bool,
90
90
  Parameter(
@@ -198,11 +198,11 @@ async def scan(
198
198
  str,
199
199
  Parameter(
200
200
  name=["--key", "-k"],
201
- help=f"The key to access the sandbox **{'**,**'.join(x.name for x in settings.sandbox_keys)}**",
201
+ help=f"The key to access the sandbox **{'**,**'.join(x.name.get_secret_value() for x in settings.sandbox_keys)}**",
202
202
  validator=validate_key,
203
203
  group="Sandbox Options",
204
204
  ),
205
- ] = settings.sandbox_keys[0].name,
205
+ ] = settings.sandbox_keys[0].name.get_secret_value(),
206
206
  is_local: Annotated[
207
207
  bool,
208
208
  Parameter(
@@ -444,11 +444,11 @@ async def scan_new(
444
444
  str,
445
445
  Parameter(
446
446
  name=["--key", "-k"],
447
- help=f"The key to access the sandbox **{'**,**'.join(x.name for x in settings.sandbox_keys)}**",
447
+ help=f"The key to access the sandbox **{'**,**'.join(x.name.get_secret_value() for x in settings.sandbox_keys)}**",
448
448
  validator=validate_key,
449
449
  group="Sandbox Options",
450
450
  ),
451
- ] = settings.sandbox_keys[0].name,
451
+ ] = settings.sandbox_keys[0].name.get_secret_value(),
452
452
  is_local: Annotated[
453
453
  bool,
454
454
  Parameter(
@@ -13,7 +13,7 @@ from sandbox_cli.models.sandbox_arguments import SandboxArguments
13
13
 
14
14
  def get_key_by_name(key_name: str) -> SandboxKey:
15
15
  for sandbox_key in settings.sandbox_keys:
16
- if sandbox_key.name == key_name:
16
+ if sandbox_key.name.get_secret_value() == key_name:
17
17
  return sandbox_key
18
18
  raise KeyError()
19
19
 
@@ -30,8 +30,9 @@ def validate_key(_: Any, value: Any) -> None:
30
30
  try:
31
31
  get_key_by_name(value)
32
32
  except KeyError:
33
+ available = "', '".join(x.name.get_secret_value() for x in settings.sandbox_keys)
33
34
  console.error(
34
- f'Key "{value}" doesn\'t exists in config. Available keys: "{'","'.join(x.name for x in settings.sandbox_keys)}"'
35
+ f'Key "{value}" doesn\'t exist in config. Available keys: "{available}"'
35
36
  )
36
37
  sys.exit(1)
37
38
 
@@ -78,11 +79,11 @@ def save_scan_arguments(out_dir: Path, scan_args: SandboxArguments) -> None:
78
79
 
79
80
 
80
81
  def open_link(link: str) -> None:
81
- if settings.browser != None:
82
+ if settings.browser is not None:
82
83
  webbrowser.register("new_default_browser", None, webbrowser.GenericBrowser([settings.browser.path, *settings.browser.args]), preferred=True)
83
84
  if not webbrowser.open(link):
84
85
  console.error("Can't open link in the specified browser. Please check browser path and args.")
85
86
  return
86
-
87
+
87
88
  if not webbrowser.open_new_tab(link):
88
89
  console.error("Can't open link in the default browser. Try adding path and args for your browser to the config file.")
@@ -18,8 +18,9 @@ from rich.markup import escape
18
18
  from rich.progress import Progress, TaskID
19
19
 
20
20
  from sandbox_cli.console import console
21
+ from sandbox_cli.internal.config import settings
21
22
 
22
- semaphore = asyncio.Semaphore(value=12)
23
+ semaphore = asyncio.Semaphore(value=16)
23
24
 
24
25
 
25
26
  async def _save_artifact(
@@ -28,6 +29,7 @@ async def _save_artifact(
28
29
  out_dir: Path,
29
30
  path: Path,
30
31
  file_uri: str,
32
+ overwrite: bool = False,
31
33
  decompress: bool = False,
32
34
  progress: Progress | None = None,
33
35
  idx: str | None = None,
@@ -40,12 +42,14 @@ async def _save_artifact(
40
42
 
41
43
  # sanitize path
42
44
  path = out_dir / Path(str(path).replace(" ", "_"))
43
- n = 1
44
- while path.exists():
45
- if not path.with_name(path.name + f"_{n}").exists():
46
- path = path.with_name(path.name + f"_{n}")
47
- break
48
- n += 1
45
+ if not overwrite:
46
+ n = 1
47
+ while path.exists():
48
+ if not path.with_name(path.name + f"_{n}").exists():
49
+ path = path.with_name(path.name + f"_{n}")
50
+ break
51
+ n += 1
52
+
49
53
  path.parent.mkdir(exist_ok=True, parents=True)
50
54
  path.touch()
51
55
  task_id: TaskID = None # type: ignore
@@ -107,7 +111,7 @@ async def download(
107
111
  ) -> None:
108
112
  tasks: list[Coroutine[Any, Any, None]] = []
109
113
 
110
- def add_task(out_dir: Path, path: Path, file_uri: str, decompress: bool = False) -> None:
114
+ def add_task(out_dir: Path, path: Path, file_uri: str, decompress: bool = False, overwrite: bool = False) -> None:
111
115
  tasks.append(
112
116
  _save_artifact(
113
117
  scan_id=report.scan_id,
@@ -120,66 +124,73 @@ async def download(
120
124
  image=image,
121
125
  link=link,
122
126
  decompress=decompress,
127
+ overwrite=overwrite,
123
128
  )
124
129
  )
125
130
 
126
131
  for artifact in report.artifacts:
127
- sandbox_result = artifact.find_sandbox_result()
128
- if sandbox_result is None:
129
- continue
132
+ for sandbox_result in artifact.get_sandbox_results():
133
+ if sandbox_result is None:
134
+ continue
130
135
 
131
- if sandbox_result.details is None:
132
- continue
136
+ if sandbox_result.details is None:
137
+ continue
133
138
 
134
- if sandbox_result.details.sandbox is None:
135
- continue
139
+ if sandbox_result.details.sandbox is None:
140
+ continue
136
141
 
137
- for log in sandbox_result.details.sandbox.logs:
138
- # download default logs by default
139
- if (all or logs) and log.type in {
140
- LogType.EVENT_CORRELATED,
141
- LogType.EVENT_NORMALIZED,
142
- LogType.EVENT_RAW,
143
- LogType.NETWORK,
144
- }:
145
- add_task(out_dir, log.file_name, log.file_uri)
142
+ if sandbox_result.details.sandbox.image and (image_id := sandbox_result.details.sandbox.image.image_id):
143
+ output = out_dir / image_id
144
+ else:
145
+ output = out_dir
146
146
 
147
- if (all or video) and log.type == LogType.SCREENSHOT:
148
- add_task(out_dir, log.file_name, log.file_uri)
147
+ for log in sandbox_result.details.sandbox.logs:
148
+ # download default logs by default
149
+ if (all or logs) and log.type in {
150
+ LogType.EVENT_CORRELATED,
151
+ LogType.EVENT_NORMALIZED,
152
+ LogType.EVENT_RAW,
153
+ LogType.NETWORK,
154
+ }:
155
+ add_task(output, log.file_name, log.file_uri, overwrite=True)
149
156
 
150
- if (all or crashdumps) and log.file_name in {"crashdump.bin", "crashdump.metadata"}:
151
- add_task(out_dir / "crashdumps", log.file_name, log.file_uri)
157
+ if (all or video) and log.type == LogType.SCREENSHOT:
158
+ add_task(output, log.file_name, log.file_uri, overwrite=True)
152
159
 
153
- if (all or debug) and log.type in {LogType.DEBUG, LogType.GRAPH}:
154
- add_task(out_dir / "debug", log.file_name, log.file_uri)
160
+ if (all or crashdumps) and log.file_name in {"crashdump.bin", "crashdump.metadata"}:
161
+ add_task(output / "crashdumps", log.file_name, log.file_uri)
155
162
 
156
- if artifacts or files or procdumps or all:
157
- if not sandbox_result.details:
158
- continue
163
+ if (all or debug) and log.type in {LogType.DEBUG, LogType.GRAPH}:
164
+ add_task(output / "debug", log.file_name, log.file_uri)
159
165
 
160
- if not sandbox_result.details.sandbox:
161
- continue
166
+ if artifacts or files or procdumps or all:
167
+ if not sandbox_result.details:
168
+ continue
162
169
 
163
- if not sandbox_result.details.sandbox.artifacts:
164
- continue
170
+ if not sandbox_result.details.sandbox:
171
+ continue
165
172
 
166
- for artifact in sandbox_result.details.sandbox.artifacts:
167
- if not artifact.file_info:
173
+ if not sandbox_result.details.sandbox.artifacts:
168
174
  continue
169
175
 
170
- if artifact.type == ArtifactType.FILE and (files or artifacts or all):
171
- add_task(
172
- out_dir / "artifacts",
173
- artifact.file_info.file_path.removeprefix("/"),
174
- artifact.file_info.file_uri,
175
- )
176
- if artifact.type == ArtifactType.PROCESS_DUMP and (procdumps or artifacts or all):
177
- add_task(
178
- out_dir / "process_dump",
179
- artifact.file_info.details.process_dump.process_name.removeprefix("/"), # type: ignore
180
- artifact.file_info.file_uri,
181
- decompress=decompress,
182
- )
176
+ for artifact in sandbox_result.details.sandbox.artifacts:
177
+ if not artifact.file_info:
178
+ continue
179
+
180
+ if artifact.type == ArtifactType.FILE and (files or artifacts or all):
181
+ add_task(
182
+ output / "artifacts",
183
+ artifact.file_info.file_path.removeprefix("/"),
184
+ artifact.file_info.file_uri,
185
+ )
186
+ if artifact.type == ArtifactType.PROCESS_DUMP and (procdumps or artifacts or all):
187
+ add_task(
188
+ output / "process_dump",
189
+ artifact.file_info.details.process_dump.process_name.removeprefix("/"), # type: ignore
190
+ artifact.file_info.file_uri,
191
+ decompress=decompress,
192
+ )
193
+
183
194
  if not tasks:
184
195
  console.info(f"Nothing to download from {report.scan_id}")
185
196
 
@@ -235,7 +235,7 @@ async def scan_internal(
235
235
  ) -> None:
236
236
  sandbox_arguments = SandboxArguments(
237
237
  type=ScanType.SCAN,
238
- sandbox_key_name=key.name,
238
+ sandbox_key_name=key.name.get_secret_value(),
239
239
  sandbox_options=sandbox_options.sandbox,
240
240
  )
241
241
  save_scan_arguments(out_dir, sandbox_arguments)
@@ -245,7 +245,7 @@ async def scan_internal(
245
245
  # except Exception as ex:
246
246
  # console.log(f"[cyan]{idx}[/] {file_path} Error: {ex!r}")
247
247
 
248
- console.info(f"Using key: name={key.name} max_workers={key.max_workers}")
248
+ console.info(f"Using key: name={key.name.get_secret_value()} max_workers={key.max_workers}")
249
249
 
250
250
  tasks: list[Coroutine[Any, Any, None]] = []
251
251
  sandbox, sandbox_options, images = await _prepare_scan_options(
@@ -327,7 +327,7 @@ async def scan_internal_advanced(
327
327
  ) -> None:
328
328
  sandbox_arguments = SandboxArguments(
329
329
  type=ScanType.SCAN_NEW,
330
- sandbox_key_name=key.name,
330
+ sandbox_key_name=key.name.get_secret_value(),
331
331
  sandbox_options=sandbox_options,
332
332
  )
333
333
  save_scan_arguments(out_dir, sandbox_arguments)
@@ -337,7 +337,7 @@ async def scan_internal_advanced(
337
337
  # except Exception as ex:
338
338
  # console.log(f"[cyan]{idx}[/] {file_path} Error: {ex!r}")
339
339
 
340
- console.info(f"Using key: name={key.name} max_workers={key.max_workers}")
340
+ console.info(f"Using key: name={key.name.get_secret_value()} max_workers={key.max_workers}")
341
341
 
342
342
  tasks: list[Coroutine[Any, Any, None]] = []
343
343
  with progress:
@@ -236,14 +236,14 @@ async def rescan_internal(
236
236
 
237
237
  await process_trace(drakvuf_trace, tcpdump_pcap, trace, out_dir, idx)
238
238
 
239
- console.info(f"Using key: name={key.name} max_workers={key.max_workers}")
239
+ console.info(f"Using key: name={key.name.get_secret_value()} max_workers={key.max_workers}")
240
240
 
241
241
  tasks: list[Coroutine[Any, Any, None]] = []
242
242
  with progress:
243
243
  sandbox, sandbox_options = await _prepare_rescan_options(progress, rules_dir, key, is_local)
244
244
  sandbox_arguments = SandboxArguments(
245
245
  type=ScanType.RE_SCAN,
246
- sandbox_key_name=key.name,
246
+ sandbox_key_name=key.name.get_secret_value(),
247
247
  sandbox_options=sandbox_options.sandbox,
248
248
  )
249
249
 
File without changes
File without changes
File without changes
File without changes