FortiSandboxv2
FortiSandbox is an advanced security tool that goes beyond standard sandboxing. It combines proactive mitigation, enhanced threat detection, and in-depth reporting, using Fortinet's dynamic antivirus technology, dual-level sandboxing, and FortiGuard cloud integration to counter advanced threats. It effectively detects viruses, Advanced Persistent Threats (APTs), and malicious URLs, integrating seamlessly with existing Fortinet devices like FortiGate and FortiMail for comprehensive network protection.
Forensics & Malware Analysis · FortiSandbox
Details
| ID | FortiSandboxv2 |
|---|---|
| Provider | Fortinet |
| Category | Forensics & Malware Analysis |
| From Version | 6.10.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
FortiSandbox is an advanced security tool that goes beyond standard sandboxing. It combines proactive mitigation, enhanced threat detection, and in-depth reporting, using Fortinet’s dynamic antivirus technology, dual-level sandboxing, and FortiGuard cloud integration to counter advanced threats. It effectively detects viruses, Advanced Persistent Threats (APTs), and malicious URLs, integrating seamlessly with existing Fortinet devices like FortiGate and FortiMail for comprehensive network protection.
This integration was integrated and tested with version 4.4.3 of FortiSandboxv2.
Some changes have been made that might affect your existing content.
If you are upgrading from a previous version of this integration, see Breaking Changes.
Configure FortiSandbox v2 on Cortex XSOAR
- Navigate to Settings > Integrations > Servers & Services.
- Search for FortiSandbox v2.
-
Click Add instance to create and configure a new integration instance.
Parameter Description Required Base URL True Username True Password True Trust any certificate (not secure) False Use system proxy settings False Source Reliability Reliability of the source providing the intelligence data. True - Click Test to validate the URLs, token, and connection.
Commands
You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
file
Runs reputation on files.
Base Command
file
Input
| Argument Name | Description | Required |
|---|---|---|
| file | List of files. Supports sha256, sha1, md5. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| File.Size | Number | The size of the file. |
| File.MD5 | String | The MD5 hash of the file. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Name | String | The name of the file. |
| File.SSDeep | String | The SSDeep hash of the file. |
| File.EntryID | String | The entry ID of the file. |
| File.Info | String | File information. |
| File.Type | String | The file type. |
| File.Extension | String | The file extension. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| DBotScore.Message | String | Optional message to show an API response. For example, “Not found”. |
Command example
!file file=936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af
Context Example
{
"DBotScore": {
"Indicator": "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af",
"Reliability": "C - Fairly reliable",
"Score": 1,
"Type": "file",
"Vendor": "FortiSandboxv2"
},
"File": {
"Extension": "txt",
"Hashes": [
{
"type": "SHA256",
"value": "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af"
}
],
"Name": "helloworld.txt",
"SHA256": "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af"
}
}
Human Readable Output
Metrics reported successfully.
url
Runs reputation on URLs.
Base Command
url
Input
| Argument Name | Description | Required |
|---|---|---|
| url | List of URLs. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| URL.Data | String | The URL. |
| URL.DetectionEngines | String | The total number of engines that checked the indicator. |
| URL.PositiveDetections | String | The number of engines that positively detected the indicator as malicious. |
| URL.Malicious.Vendor | String | The vendor reporting the URL as malicious. |
| URL.Malicious.Description | String | A description of the malicious URL. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| DBotScore.Message | String | Optional message to show an API response. For example, “Not found”. |
Command example
!url url=www.google.com
Context Example
{
"DBotScore": {
"Indicator": "www.google.com",
"Reliability": "C - Fairly reliable",
"Score": 1,
"Type": "url",
"Vendor": "FortiSandboxv2"
},
"URL": {
"Data": "www.google.com"
}
}
Human Readable Output
Metrics reported successfully.
fortisandbox-submission-file-upload
Scheduled command to upload any file type to be sandboxed. The system swiftly identifies and mitigates threats in files.
Base Command
fortisandbox-submission-file-upload
Input
| Argument Name | Description | Required |
|---|---|---|
| entry_id | An entry ID of any file to be uploaded for analysis. | Required |
| comment | Comment field, max characters allowed: 255. | Optional |
| process_timeout | Cancel processing a submission when timeout in seconds before entering virtual machine. | Optional |
| skip_steps | Comma-separated list of steps to skip from file analysis. Do not use this parameter if no step to skip. Possible values are: anti_virus, cloud, sandbox, static_scan. | Optional |
| archive_passwords | Comma-separated list of passwords needed for extracting archived/zipped files. Non-ASCII passwords are invalid. | Optional |
| overwrite_vm_list | Comma-separated list of virtual machines to use. If this field is not set, default ones will be used. | Optional |
| force_vm_scan | Whether to force the file to be scanned in a virtual machine. Possible values are: true, false. Default is false. | Optional |
| add_to_threat_package | Specifies whether the uploaded sample should be included in the threat package, based on meeting certain malware criteria. When set to true, the system will evaluate the sample and, if it qualifies, add it to the malware package. The default setting is false, indicating that the sample will not be added unless explicitly requested. Possible values are: false, true. Default is false. | Optional |
| record | Record scan process in video if VMs are involved. Possible values are: true, false. Default is false. | Optional |
| enable_ai | Enable Deep-AI mode for this scanning. Possible values are: true, false. Default is false. | Optional |
| get_scan_report | Whether to return a PDF scan report at the end of the file analysis. Possible values are: true, false. Default is false. | Optional |
| interval | The interval between each poll in seconds. Min value is 10. Default is 30. |
Optional |
| timeout | The timeout for the polling in seconds. Default is 600. | Optional |
| sid | The submission ID. Hidden argument. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FortiSandbox.Submission.name | String | The input file name. |
| FortiSandbox.Submission.sid | String | The ID of the submission. |
| FortiSandbox.Submission.jid | String | The ID of the job. |
| FortiSandbox.Submission.start_ts | Number | Start scan time in epoch, UTC. |
| FortiSandbox.Submission.finish_ts | Number | Finish scan time in epoch, UTC. |
| FortiSandbox.Submission.now | Number | FortiSandbox’s time in epoch, UTC. |
| FortiSandbox.Submission.untrusted | Number | 0: the result can be trusted 1: since this file’s scan, scan environment has changed. |
| FortiSandbox.Submission.rating | String | The rating can be one or more of the following: Clean, Low Risk, Medium Risk, High Risk, Malicious, or Other. For archive files, the possible ratings of all files in the archive are displayed. During the file scan, the rating is displayed as N/A. If a scan times out or is terminated by the system, the file will have an Other rating. |
| FortiSandbox.Submission.score | Number | One of the following: `RISK_UNKNOWN -1`, `RISK_CLEAN 0`, `RISK_MALICIOUS 1`, `RISK_HIGH 2`, `RISK_MEDIUM 3`, `RISK_LOW 4`. |
| FortiSandbox.Submission.sha256 | String | The SHA256 of the submitted file. |
| FortiSandbox.Submission.sha1 | String | The SHA1 of the submitted file. |
| FortiSandbox.Submission.malware_name | String | Virus name if it’s a known virus. |
| FortiSandbox.Submission.vid | Number | The virus ID. Detailed information of the virus can be found at: `http://www.fortiguard.com/encyclopedia/virus/#id=virus_id` by replacing `virus_id` with the given value. |
| FortiSandbox.Submission.infected_os | String | The OS version of the FortiSandbox VM that was used to make the suspicious verdict. |
| FortiSandbox.Submission.detection_os | String | The name of the virtual machine images that scanned the file. |
| FortiSandbox.Submission.rating_source | String | One of: `AV Scan`, `Cloud Query`, `Sandboxing`, `Static Scan`, `Other`. |
| FortiSandbox.Submission.category | String | One of: `Clean`, `Unknown`, `Infector`, `Worm`, `Botnet`, `Hijack`, `Stealer`, `Backdoor`, `Injector`, `Rootkit`, `Adware`, `Dropper`, `Downloader`, `Trojan`, `Riskware`, `Grayware`, or `Attacker`. |
| FortiSandbox.Submission.detail_url | String | URL to the job overview. |
| FortiSandbox.Submission.download_url | String | The input file name encoded in Base64. |
| FortiSandbox.Submission.false_positive_negative | Number | Not false positive or false negative, 1: false positive, 2: false negative. |
| FortiSandbox.Submission.file_name | String | The name of the submitted file. |
| File.Size | Number | The size of the file. |
| File.MD5 | String | The MD5 hash of the file. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Name | String | The name of the file. |
| File.SSDeep | String | The SSDeep hash of the file. |
| File.EntryID | String | The entry ID of the file. |
| File.Info | String | File information. |
| File.Type | String | The file type. |
| File.Extension | String | The file extension. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| DBotScore.Message | String | Optional message to show an API response. For example, “Not found”. |
Command example
!fortisandbox-submission-file-upload entry_id=418@e75b29e7-17a8-41bc-8555-ef233dd8bac9
Human Readable Output
No jobs were created yet for the submission 7048126795285831956
fortisandbox-submission-url-upload
Scheduled command to upload URLs through a text file or directly to be sandboxed individually. The system rigorously examines URLs for online security hazards.
Base Command
fortisandbox-submission-url-upload
Input
| Argument Name | Description | Required |
|---|---|---|
| entry_id | An entry ID of a text file to be uploaded for analysis. Each URL within file the must be separated with new lines. | Optional |
| urls | Comma-separated list of URLs to upload to scan. | Optional |
| comment | Comment field, max characters allowed: 255. | Optional |
| process_timeout | The time period to stop the URLs scan, in seconds (between 30 and 1200 seconds). | Optional |
| depth | The recursive depth in which URLs are examined. Level 0 for original URL page (between 0 and 5). | Optional |
| overwrite_vm_list | Comma-separated list of virtual machines to use. If this field is not set, default ones will be used. | Optional |
| force_vm_scan | Whether to force the file to be scanned in a virtual machine. Possible values are: true, false. Default is false. | Optional |
| add_to_threat_package | Specifies whether the uploaded sample should be included in the threat package, based on meeting certain malware criteria. When set to true, the system will evaluate the sample and, if it qualifies, add it to the malware package. The default setting is false, indicating that the sample will not be added unless explicitly requested. Possible values are: false, true. Default is false. | Optional |
| record | Record scan process in video if VMs are involved. Possible values are: true, false. | Optional |
| enable_ai | Enable Deep-AI mode for this scanning. Possible values are: true, false. | Optional |
| get_scan_report | Whether to return a PDF scan report at the end of the file analysis. Note: Generating PDF scan reports can be time-consuming, especially when analyzing multiple URLs. Possible values are: true, false. Default is false. | Optional |
| interval | The interval between each poll in seconds. Min value is 10. Default is 30. |
Optional |
| timeout | The timeout for the polling in seconds. Default is 600. | Optional |
| sid | The submission ID. Hidden argument. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FortiSandbox.Submission.name | String | The input URL/file name. |
| FortiSandbox.Submission.sid | String | The ID of the submission. |
| FortiSandbox.Submission.jid | String | The ID of the job. |
| FortiSandbox.Submission.start_ts | Number | Start scan time in epoch, UTC. |
| FortiSandbox.Submission.finish_ts | Number | Finish scan time in epoch, UTC. |
| FortiSandbox.Submission.now | Number | FortiSandbox’s time in epoch, UTC. |
| FortiSandbox.Submission.untrusted | Number | 0: the result can be trusted 1: since this file’s scan, scan environment has changed. |
| FortiSandbox.Submission.rating | String | The rating can be one or more of the following: Clean, Low Risk, Medium Risk, High Risk, Malicious, or Other. For archive files, the possible ratings of all files in the archive are displayed. During the file scan, the rating is displayed as N/A. If a scan times out or is terminated by the system, the file will have an Other rating. |
| FortiSandbox.Submission.score | Number | One of the following: `RISK_UNKNOWN -1`, `RISK_CLEAN 0`, `RISK_MALICIOUS 1`, `RISK_HIGH 2`, `RISK_MEDIUM 3`, `RISK_LOW 4`. |
| FortiSandbox.Submission.sha256 | String | The SHA256 of the submitted file. |
| FortiSandbox.Submission.sha1 | String | The SHA1 of the submitted file. |
| FortiSandbox.Submission.malware_name | String | Virus name if it’s a known virus. |
| FortiSandbox.Submission.vid | Number | The virus ID. Detailed information of the virus can be found at: `http://www.fortiguard.com/encyclopedia/virus/#id=virus_id` by replacing `virus_id` with the given value. |
| FortiSandbox.Submission.infected_os | String | The OS version of the FortiSandbox VM that was used to make the suspicious verdict. |
| FortiSandbox.Submission.detection_os | String | The name of the virtual machine images that scanned the file. |
| FortiSandbox.Submission.rating_source | String | One of: `AV Scan`, `Cloud Query`, `Sandboxing`, `Static Scan`, `Other`. |
| FortiSandbox.Submission.category | String | One of: `Clean`, `Unknown`, `Infector`, `Worm`, `Botnet`, `Hijack`, `Stealer`, `Backdoor`, `Injector`, `Rootkit`, `Adware`, `Dropper`, `Downloader`, `Trojan`, `Riskware`, `Grayware`, or `Attacker`. |
| FortiSandbox.Submission.detail_url | String | URL to the job overview. |
| FortiSandbox.Submission.download_url | String | The input URL encoded in Base64. |
| FortiSandbox.Submission.false_positive_negative | Number | Not false positive or false negative, 1: false positive, 2: false negative |
| FortiSandbox.Submission.file_name | String | The name of the submitted file. |
| URL.Data | String | The URL. |
| URL.DetectionEngines | String | The total number of engines that checked the indicator. |
| URL.PositiveDetections | String | The number of engines that positively detected the indicator as malicious. |
| URL.Malicious.Vendor | String | The vendor reporting the URL as malicious. |
| URL.Malicious.Description | String | A description of the malicious URL. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| DBotScore.Message | String | Optional message to show an API response. For example, “Not found”. |
Command example
!fortisandbox-submission-url-upload urls=www.google.com
Human Readable Output
No jobs were created yet for the submission 7048126856924000534
fortisandbox-submission-cancel
Cancel a running job submission. Note: Jobs that are already being processed cannot be canceled, only jobs that are in the queue.
Base Command
fortisandbox-submission-cancel
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The submission ID. | Required |
Context Output
There is no context output for this command.
Command example
!fortisandbox-submission-cancel id=7047969418633282747
Human Readable Output
The cancellation of the submission 7047969418633282747 was successfully sent
fortisandbox-submission-job-verdict
Get the verdict of the provided job.
Base Command
fortisandbox-submission-job-verdict
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The job ID. Use !forisandbox-submission-job-list to fetch a list of job IDs. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| FortiSandbox.Submission.name | String | The input URL/file name. |
| FortiSandbox.Submission.start_ts | Number | Start scan time in epoch, UTC. |
| FortiSandbox.Submission.finish_ts | Number | Finish scan time in epoch, UTC. |
| FortiSandbox.Submission.now | Number | FortiSandbox’s time in epoch, UTC. |
| FortiSandbox.Submission.behavior_info | Number | 0: There is no analytic report for this URL. 1: There is an analytic report for this URL. |
| FortiSandbox.Submission.category | String | One of: `Clean`, `Unknown`, `Infector`, `Worm`, `Botnet`, `Hijack`, `Stealer`, `Backdoor`, `Injector`, `Rootkit`, `Adware`, `Dropper`, `Downloader`, `Trojan`, `Riskware`, `Grayware`, or `Attacker`. |
| FortiSandbox.Submission.detection_os | String | The name of the virtual machine images that scanned the file. |
| FortiSandbox.Submission.false_positive_negative | Number | Not false positive or false negative, 1: false positive, 2: false negative. |
| FortiSandbox.Submission.infected_os | String | The OS version of the FortiSandbox VM that was used to make the suspicious verdict. |
| FortiSandbox.Submission.malware_name | String | Virus name if it’s a known virus. |
| FortiSandbox.Submission.rating | String | The rating can be one or more of the following: Clean, Low Risk, Medium Risk, High Risk, Malicious, or Other. For archive files, the possible ratings of all files in the archive are displayed. During the file scan, the rating is displayed as N/A. If a scan times out or is terminated by the system, the file will have an Other rating. |
| FortiSandbox.Submission.rating_source | String | One of: `AV Scan`, `Cloud Query`, `Sandboxing`, `Static Scan`, `Other`. |
| FortiSandbox.Submission.score | Number | One of the following: `RISK_UNKNOWN -1`, `RISK_CLEAN 0`, `RISK_MALICIOUS 1`, `RISK_HIGH 2`, `RISK_MEDIUM 3`, `RISK_LOW 4`. |
| FortiSandbox.Submission.untrusted | Number | 0: the result can be trusted 1: since this files’ scan, scan environment has changed. |
| FortiSandbox.Submission.vid | Number | The virus ID. Detailed information of the virus can be found at: `http://www.fortiguard.com/encyclopedia/virus/#id=virus_id` by replacing `virus_id` with the given value. |
| FortiSandbox.Submission.detail_url | String | URL to the job overview. |
| FortiSandbox.Submission.download_url | String | The input URL/file name encoded in Base64. |
| FortiSandbox.Submission.jid | String | The ID of the job. |
| FortiSandbox.Submission.sha1 | String | The SHA1 hash of the file. |
| FortiSandbox.Submission.sha256 | String | The SHA256 hash of the file. |
| File.Size | Number | The size of the file. |
| File.MD5 | String | The MD5 hash of the file. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Name | String | The name of the file. |
| File.SSDeep | String | The SSDeep hash of the file. |
| File.EntryID | String | The entry ID of the file. |
| File.Info | String | File information. |
| File.Type | String | The file type. |
| File.Extension | String | The file extension. |
| URL.Data | String | The URL. |
| URL.DetectionEngines | String | The total number of engines that checked the indicator. |
| URL.PositiveDetections | String | The number of engines that positively detected the indicator as malicious. |
| URL.Malicious.Vendor | String | The vendor reporting the URL as malicious. |
| URL.Malicious.Description | String | A description of the malicious URL. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| DBotScore.Message | String | Optional message to show an API response. For example, “Not found”. |
Command example
!fortisandbox-submission-job-verdict id=7047959279104315513
Context Example
{
"DBotScore": {
"Indicator": "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af",
"Message": "https://0.0.0.0/job-detail/?sid=7047959252528592869&jid=7047959279104315513&req_type=file-csearch",
"Reliability": "C - Fairly reliable",
"Score": 1,
"Type": "file",
"Vendor": "FortiSandboxv2"
},
"File": {
"Extension": "txt",
"Hashes": [
{
"type": "SHA1",
"value": "6adfb183a4a2c94a2f92dab5ade762a47889a5a1"
},
{
"type": "SHA256",
"value": "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af"
}
],
"Name": "helloworld.txt",
"SHA1": "6adfb183a4a2c94a2f92dab5ade762a47889a5a1",
"SHA256": "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af"
},
"FortiSandbox": {
"Submission": {
"category": "NotApplicable",
"detail_url": "https://0.0.0.0/job-detail/?sid=7047959252528592869&jid=7047959279104315513&req_type=file-csearch",
"detection_os": "",
"download_url": "aGVsbG93b3JsZC50eHQK",
"false_positive_negative": 0,
"file_name": "helloworld.txt",
"finish_ts": 1710245223,
"ftype": "txt",
"infected_os": "",
"jid": "7047959279104315513",
"malware_name": "N/A",
"name": "helloworld.txt\n",
"now": 1710254987,
"rating": "Clean",
"rating_source": "Static Scan Engine",
"score": 0,
"sha1": "6adfb183a4a2c94a2f92dab5ade762a47889a5a1",
"sha256": "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af",
"start_ts": 1710245223,
"untrusted": 1,
"vid": 0
}
}
}
Human Readable Output
The verdict for the job 7047959279104315513
Jid Name Start Ts Finish Ts Category Malware Name Rating Detail Url 7047959279104315513 helloworld.txt 1710245223 1710245223 NotApplicable N/A Clean https://0.0.0.0/job-detail/?sid=7047959252528592869&jid=7047959279104315513&req_type=file-csearch
fortisandbox-submission-job-list
Get a list of jobs that were created from a submission.
Base Command
fortisandbox-submission-job-list
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The submission ID. Use !fortisandbox-submission-file-upload or !fortisandbox-submission-url-upload to create a submission. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| FortiSandbox.Submission.sid | String | The ID of the submission. |
| FortiSandbox.Submission.jid | String | The ID of the job. |
Command example
!fortisandbox-submission-job-list id=7047969418633282747
Context Example
{
"FortiSandbox": {
"Submission": {
"jid": "7047969436160637757",
"sid": "7047969418633282747"
}
}
}
Human Readable Output
The submission 7047969418633282747 job IDs
Jid 7047969436160637757
fortisandbox-submission-job-report
Get a PDF report of the provided submission.
Base Command
fortisandbox-submission-job-report
Input
| Argument Name | Description | Required |
|---|---|---|
| identifier | The job ID or SHA256 of the scanned file or URL. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| InfoFile.Name | String | File name. |
| InfoFile.EntryID | String | The entry ID of the report. |
| InfoFile.Size | Number | File size. |
| InfoFile.Type | String | File type “pdf”. |
| InfoFile.Info | String | Basic information of the file. |
Command example
!fortisandbox-submission-job-report identifier=7047959279104315513
Context Example
{
"InfoFile": {
"EntryID": "449@e75b29e7-17a8-41bc-8555-ef233dd8bac9",
"Extension": "pdf",
"Info": "application/pdf",
"Name": "7047959279104315513.pdf",
"Size": 2605722,
"Type": "PDF document, version 1.4"
}
}
Human Readable Output
Breaking changes from the previous version of this integration - FortiSandbox v2
Commands
The following commands were removed in this version
- fortisandbox-simple-file-rating-sha256 - this command was replaced by file.
- fortisandbox-simple-file-rating-sha1 - this command was replaced by file.
- fortisandbox-url-rating - this command was replaced by url.
- fortisandbox-get-file-verdict-detailed - this command was replaced by file.
- fortisandbox-upload-file - this command was replaced by fortisandbox-submission-upload-file.
- fortisandbox-query-job-verdict - this command was replaced by fortisandbox-submission-job-verdict.
- fortisandbox-jobid-from-submission - this command was replaced by fortisandbox-submission-job-list.
- fortisandbox-get-pdf-report - this command was replaced by fortisandbox-submission-job-report.
- fortisandbox-upload-urls - this command was replaced by fortisandbox-submission-upload-url.
Configuration parameters
base_url— Base URL (required)credentials— Username (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settingsintegration_reliability— Source Reliability (required)
Commands (8)
-
fileRuns reputation on files.
-
fortisandbox-submission-cancelCancel a running job submission. Note: Jobs that are already being processed cannot be canceled, only jobs that are in the queue.
-
fortisandbox-submission-file-uploadScheduled command to upload any file type to be sandboxed. The system swiftly identifies and mitigates threats in files.
-
fortisandbox-submission-job-listGet a list of jobs that were created from a submission.
-
fortisandbox-submission-job-reportGet a PDF report of the provided submission.
-
fortisandbox-submission-job-verdictGet the verdict of the provided job.
-
fortisandbox-submission-url-uploadScheduled command to upload URLs through a text file or directly to be sandboxed individually. The system rigorously examines URLs for online security hazards.
-
urlRuns reputation on URLs.
import json import os import unittest.mock from typing import Any import CommonServerPython import FortiSandboxv2 import pytest from FortiSandboxv2 import is_url TEST_DATA = "test_data" BASE_URL = "https://www.example.com" API_URL = CommonServerPython.urljoin(BASE_URL, "jsonrpc/") """ Utils """ def load_mock_response(file_name: str) -> dict[str, Any]: """Load mock file that simulates an API response. Args: file_name (str): Name of the mock response JSON file to return. Returns: str: Mock file content. """ file_path = os.path.join(TEST_DATA, file_name) with open(file_path, encoding="utf-8") as mock_file: return json.loads(mock_file.read()) """ Fixtures """ @pytest.fixture() def mock_client() -> FortiSandboxv2.Client: """ Establish a mock connection to the client with a username and password. Returns: Client: Mock connection to client. """ return FortiSandboxv2.Client( base_url=BASE_URL, username="Pokemon", password="Pikachu", ) """ Helper Tests """ def test_bool_to_int(): """Test the bool_to_int function. Ensure: - False is converted to 0. - True is converted to 1. """ assert FortiSandboxv2.bool_to_int(False) == 0 assert FortiSandboxv2.bool_to_int(True) == 1 def test_bool_to_str(): """Test the bool_to_str function. Ensure: - False is converted to "0". - True is converted to "1". """ assert FortiSandboxv2.bool_to_str(False) == "0" assert FortiSandboxv2.bool_to_str(True) == "1" @pytest.mark.parametrize( "indicator,indicator_type,score,rating,detail_url", [ ("pikachu.exe", CommonServerPython.DBotScoreType.FILE, -1, None, "hello"), ("pikachu.exe", CommonServerPython.DBotScoreType.FILE, None, "Unknown", None), ("pikachu.exe", CommonServerPython.DBotScoreType.FILE, None, ["Unknown"], None), ("pikachu.exe", CommonServerPython.DBotScoreType.FILE, None, None, "hello"), ("pikachu.com", CommonServerPython.DBotScoreType.URL, -1, None, "hello"), ], ) def test_build_dbot_score( indicator: str, indicator_type: str, score: int | None, rating: list[str] | str | None, detail_url: str | None, ): """Test the build_dbot_score function. Ensure: - The indicator is set to the expected indicator value. - The indicator type is set to the expected indicator type. - The score is set to Common.DBotScore.NONE. - The reliability is set to Common.DBotScoreReliability.C. - The message is set to the detail URL. Args: indicator (str): The indicator value. indicator_type (str): The type of the indicator. score (int | None): The score value. rating (list[str] | str | None): The rating value. detail_url (str | None): The detail URL. """ dbot_score = FortiSandboxv2.build_dbot_score( indicator=indicator, indicator_type=indicator_type, score=score, rating=rating, detail_url=detail_url, ) assert dbot_score.indicator == indicator assert dbot_score.indicator_type == indicator_type assert dbot_score.score == CommonServerPython.Common.DBotScore.NONE assert dbot_score.reliability == CommonServerPython.DBotScoreReliability.C assert dbot_score.message == detail_url def test_build_relationship(): """Test the build_relationship function. Ensure: - The entity is set to the expected entity value. """ entity_type = CommonServerPython.FeedIndicatorType.File entity = "pikachu.exe" malware = "pikachu" output = FortiSandboxv2.build_relationship( entity_type=entity_type, entity=entity, malware=malware, ) expected_result = CommonServerPython.EntityRelationship( name=CommonServerPython.EntityRelationship.Relationships.INDICATOR_OF, entity_a=entity, entity_a_type=entity_type, entity_b=malware, entity_b_type=CommonServerPython.FeedIndicatorType.Malware, reverse_name=CommonServerPython.EntityRelationship.Relationships.INDICATED_BY, brand="FortiSandbox", source_reliability=CommonServerPython.DBotScoreReliability.C, ) assert output.to_context() == expected_result.to_context() @pytest.mark.parametrize( "data,url,file_hash,expected_result", [ ( { "score": 3, "malware_name": "thunderbolt", "detail_url": "https://0.0.0.0/job-detail/?sid=0&jid=0&req_type=url-csearch", "download_url": "d3d3LnBva2Vtb24uY29t", "category": "pokemon", }, None, None, CommonServerPython.Common.URL( dbot_score=CommonServerPython.Common.DBotScore( indicator="www.pokemon.com", indicator_type=CommonServerPython.DBotScoreType.URL, score=CommonServerPython.Common.DBotScore.SUSPICIOUS, reliability=FortiSandboxv2.RELIABILITY, message="https://0.0.0.0/job-detail/?sid=0&jid=0&req_type=url-csearch", ), url="www.pokemon.com", category="pokemon", malware_family=["thunderbolt"], relationships=[ CommonServerPython.EntityRelationship( name=CommonServerPython.EntityRelationship.Relationships.INDICATOR_OF, entity_a="www.pokemon.com", entity_a_type=CommonServerPython.FeedIndicatorType.URL, entity_b="thunderbolt", entity_b_type=CommonServerPython.FeedIndicatorType.Malware, reverse_name=CommonServerPython.EntityRelationship.Relationships.INDICATED_BY, brand="FortiSandbox", source_reliability=FortiSandboxv2.RELIABILITY, ) ], ), ), ( { "rating": "High Risk", "malware_name": "N/A", "detail_url": "https://0.0.0.0/job-detail/?sid=0&jid=0&req_type=url-csearch", "url": "www.pokemon.com", "category": "NotApplicable", }, None, None, CommonServerPython.Common.URL( dbot_score=CommonServerPython.Common.DBotScore( indicator="www.pokemon.com", indicator_type=CommonServerPython.DBotScoreType.URL, score=CommonServerPython.Common.DBotScore.BAD, reliability=FortiSandboxv2.RELIABILITY, message="https://0.0.0.0/job-detail/?sid=0&jid=0&req_type=url-csearch", ), url="www.pokemon.com", ), ), ( { "rating": "High Risk", }, "www.pokemon.com", None, CommonServerPython.Common.URL( dbot_score=CommonServerPython.Common.DBotScore( indicator="www.pokemon.com", indicator_type=CommonServerPython.DBotScoreType.URL, score=CommonServerPython.Common.DBotScore.BAD, reliability=FortiSandboxv2.RELIABILITY, ), url="www.pokemon.com", ), ), ( { "score": 3, "malware_name": "thunderbolt", "detail_url": "https://0.0.0.0/job-detail/?sid=0&jid=0&req_type=file-csearch", "sha256": "0000000000000000000000000000000000000000000000000000000000000000", "sha1": "0000000000000000000000000000000000000000", "file_name": "pikachu.exe", }, None, None, CommonServerPython.Common.File( dbot_score=CommonServerPython.Common.DBotScore( indicator="0000000000000000000000000000000000000000000000000000000000000000", indicator_type=CommonServerPython.DBotScoreType.FILE, score=CommonServerPython.Common.DBotScore.SUSPICIOUS, reliability=FortiSandboxv2.RELIABILITY, message="https://0.0.0.0/job-detail/?sid=0&jid=0&req_type=file-csearch", ), name="pikachu.exe", extension="exe", malware_family=["thunderbolt"], sha1="0000000000000000000000000000000000000000", sha256="0000000000000000000000000000000000000000000000000000000000000000", relationships=[ CommonServerPython.EntityRelationship( name=CommonServerPython.EntityRelationship.Relationships.INDICATOR_OF, entity_a="0000000000000000000000000000000000000000000000000000000000000000", entity_a_type=CommonServerPython.FeedIndicatorType.File, entity_b="thunderbolt", entity_b_type=CommonServerPython.FeedIndicatorType.Malware, reverse_name=CommonServerPython.EntityRelationship.Relationships.INDICATED_BY, brand="FortiSandbox", source_reliability=FortiSandboxv2.RELIABILITY, ) ], ), ), ( { "rating": ["High Risk"], "malware_name": ["thunderbolt", "N/A"], "detail_url": "https://0.0.0.0/job-detail/?sid=0&jid=0&req_type=file-csearch", }, None, "0000000000000000000000000000000000000000000000000000000000000000", CommonServerPython.Common.File( dbot_score=CommonServerPython.Common.DBotScore( indicator="0000000000000000000000000000000000000000000000000000000000000000", indicator_type=CommonServerPython.DBotScoreType.FILE, score=CommonServerPython.Common.DBotScore.BAD, reliability=FortiSandboxv2.RELIABILITY, message="https://0.0.0.0/job-detail/?sid=0&jid=0&req_type=file-csearch", ), malware_family=["thunderbolt"], sha256="0000000000000000000000000000000000000000000000000000000000000000", relationships=[ CommonServerPython.EntityRelationship( name=CommonServerPython.EntityRelationship.Relationships.INDICATOR_OF, entity_a="0000000000000000000000000000000000000000000000000000000000000000", entity_a_type=CommonServerPython.FeedIndicatorType.File, entity_b="thunderbolt", entity_b_type=CommonServerPython.FeedIndicatorType.Malware, reverse_name=CommonServerPython.EntityRelationship.Relationships.INDICATED_BY, brand="FortiSandbox", source_reliability=FortiSandboxv2.RELIABILITY, ) ], ), ), ], ) def test_build_indicator( data: dict[str, Any], url: str | None, file_hash: str | None, expected_result: CommonServerPython.Common.Indicator, ): """Test the build_indicator function. Ensure: - The indicator is set to the expected indicator value. Args: data (dict[str, Any]): The data to build the indicator from. url (str | None): The URL to build the indicator from. file_hash (str | None): The file hash to build the indicator from. expected_result (CommonServerPython.Common.Indicator): The expected indicator. """ indicator = FortiSandboxv2.build_indicator(data, url, file_hash) assert indicator.to_context() == expected_result.to_context() @pytest.mark.parametrize( "args,expected_result", [ ( {"urls": ["https://pikachu.com", "www.pokemon.com"]}, ("dXJsc19mb3JfdXBsb2FkXzE2MDk0NTkyMDAudHh0", "aHR0cHM6Ly9waWthY2h1LmNvbQp3d3cucG9rZW1vbi5jb20="), ), ( {"entry_id": "123"}, ("cGlrYWNodS5leGU=", "aHR0cHM6Ly9waWthY2h1LmNvbQp3d3cucG9rZW1vbi5jb20="), ), ], ) @unittest.mock.patch("FortiSandboxv2.time.time", return_value=1609459200) @unittest.mock.patch("FortiSandboxv2.demisto.getFilePath", return_value={"path": "/path", "name": "pikachu.exe"}) def test_prepare_submission_content( mocked_time, mocked_get_file_path, args: dict[str, Any], expected_result: tuple[str, str], ): """Test the prepare_submission_content function. Ensure: - The file name and content is set to the expected file name and content. Args: mocked_time (MagicMock): A mock for the `time.time` function to return a fixed timestamp, ensuring the generated file name's timestamp component is predictable for the test. mocked_get_file_path (MagicMock): A mock for the `demisto.getFilePath` function to simulate retrieving the file path and name when an `entry_id` is provided, allowing for testing of the file upload functionality without accessing the file system. args (dict[str, Any]): The arguments to pass to the function. expected_result (tuple[str, str]): The expected result. """ mocked_open = unittest.mock.mock_open(read_data="https://pikachu.com\nwww.pokemon.com") with unittest.mock.patch("builtins.open", mocked_open): file_name, content = FortiSandboxv2.prepare_submission_content(args) assert (file_name, content) == expected_result @pytest.mark.parametrize( "args", [ ({}), ({"entry_id": "123", "urls": ["https://pikachu.com"]}), ], ) def test_prepare_submission_content_error(args: dict[str, Any]): """Test the prepare_submission_content function with an error. Ensure: - A DemistoException is raised. Args: args (dict[str, Any]): The arguments to pass to the function. """ with pytest.raises(CommonServerPython.DemistoException): FortiSandboxv2.prepare_submission_content(args) @pytest.mark.parametrize( "args,integration_context,file_names,expected_context_list,expected_poll_result", [ ( {"sid": "123"}, {}, [ "job_list_empty.json", ], [ { "total_jids": 0, "fetched_jids": [], "remaining_jids": [], "jid_to_raw_response": {}, } ], CommonServerPython.PollResult( response=None, continue_to_poll=True, args_for_next_run={"sid": "123"}, partial_result=CommonServerPython.CommandResults( readable_output="## No jobs were created yet for the submission 123." ), ), ), ( {"sid": "123"}, { "total_jids": 3, "fetched_jids": ["000"], "remaining_jids": ["111"], "jid_to_raw_response": { "000": load_mock_response("job_verdict.json"), }, }, [ "job_list_done.json", "job_verdict.json", "job_verdict.json", ], [ { "total_jids": 3, "fetched_jids": ["111", "222", "000"], "remaining_jids": [], }, {}, ], CommonServerPython.PollResult( response=[ CommonServerPython.CommandResults( indicator=CommonServerPython.Common.URL( dbot_score=CommonServerPython.Common.DBotScore( indicator="www.pokemon.com", indicator_type=CommonServerPython.DBotScoreType.URL, score=CommonServerPython.Common.DBotScore.GOOD, reliability=FortiSandboxv2.RELIABILITY, message="https://pikachu/job-detail/?sid=456&jid=123&req_type=url-csearch", ), url="www.pokemon.com", ), ), CommonServerPython.CommandResults( indicator=CommonServerPython.Common.URL( dbot_score=CommonServerPython.Common.DBotScore( indicator="www.pokemon.com", indicator_type=CommonServerPython.DBotScoreType.URL, score=CommonServerPython.Common.DBotScore.GOOD, reliability=FortiSandboxv2.RELIABILITY, message="https://pikachu/job-detail/?sid=456&jid=123&req_type=url-csearch", ), url="www.pokemon.com", ), ), CommonServerPython.CommandResults( indicator=CommonServerPython.Common.URL( dbot_score=CommonServerPython.Common.DBotScore( indicator="www.pokemon.com", indicator_type=CommonServerPython.DBotScoreType.URL, score=CommonServerPython.Common.DBotScore.GOOD, reliability=FortiSandboxv2.RELIABILITY, message="https://pikachu/job-detail/?sid=456&jid=123&req_type=url-csearch", ), url="www.pokemon.com", ), ), ], continue_to_poll=False, ), ), ], ) def test_poll_job_submissions( requests_mock, mock_client: FortiSandboxv2.Client, args: dict[str, Any], integration_context: dict[str, Any], file_names: list[str], expected_context_list: list[dict[str, Any]], expected_poll_result: CommonServerPython.PollResult, ): """Test the poll_job_submissions function. Ensure: - The integration context is set to the expected integration context. - The poll result is set to the expected poll result. Args: requests_mock (pytest_mock.plugin.MockerFixture): Mocked requests. mock_client (FortiSandboxv2.Client): Mocked client. args (dict[str, Any]): The arguments to pass to the function. integration_context (dict[str, Any]): The integration context to patch. file_names (list[str]): The file names for the mocked responses. expected_context_list (list[dict[str, Any]]): A list of the expected integration context. expected_poll_result (CommonServerPython.PollResult): The expected poll result. """ requests_mock.post( API_URL, [{"json": load_mock_response(file_name)} for file_name in file_names], ) with ( unittest.mock.patch("FortiSandboxv2.get_integration_context", return_value=integration_context), unittest.mock.patch("FortiSandboxv2.set_integration_context") as mock_set_integration_context, ): poll_result = FortiSandboxv2.poll_job_submissions(client=mock_client, args=args) for call_args, expected_context in zip(mock_set_integration_context.call_args_list, expected_context_list): args = call_args.args[0] assert set(args.get("fetched_jids", [])) == set(expected_context.get("fetched_jids", [])) assert set(args.get("remaining_jids", [])) == set(expected_context.get("remaining_jids", [])) assert args.get("total_jids") == expected_context.get("total_jids") assert poll_result.continue_to_poll == expected_poll_result.continue_to_poll assert poll_result.args_for_next_run == expected_poll_result.args_for_next_run if poll_result.response or expected_poll_result.response: for actual_response, expected_response in zip(poll_result.response, expected_poll_result.response): assert actual_response.indicator.to_context() == expected_response.indicator.to_context() if poll_result.partial_result or expected_poll_result.partial_result: assert poll_result.partial_result.to_context() == expected_poll_result.partial_result.to_context() """ Command Tests """ def test_test_module(requests_mock, mock_client: FortiSandboxv2.Client): """Test the test_module function. Ensure: - The result is set to "ok". Args: requests_mock (pytest_mock.plugin.MockerFixture): Mocked requests. mock_client (FortiSandboxv2.Client): Mocked client. """ requests_mock.post(API_URL, json={"result": {"status": {"code": 0}}}) result = FortiSandboxv2.test_module(client=mock_client) assert result == "ok" @pytest.mark.parametrize( "file_name,expected_outputs", [ ( "url_rating_known.json", [ CommonServerPython.Common.URL( dbot_score=CommonServerPython.Common.DBotScore( indicator="https://www.pokemon.com", indicator_type=CommonServerPython.DBotScoreType.URL, score=CommonServerPython.Common.DBotScore.GOOD, reliability=FortiSandboxv2.RELIABILITY, message="", ), url="https://www.pokemon.com", ), CommonServerPython.Common.URL( dbot_score=CommonServerPython.Common.DBotScore( indicator="http://pikachu.com", indicator_type=CommonServerPython.DBotScoreType.URL, score=CommonServerPython.Common.DBotScore.BAD, reliability=FortiSandboxv2.RELIABILITY, message="", ), url="http://pikachu.com", ), ], ), ( "url_rating_unknown.json", [ CommonServerPython.create_indicator_result_with_dbotscore_unknown( indicator="https://www.charizard.com", indicator_type=CommonServerPython.DBotScoreType.URL, reliability=FortiSandboxv2.RELIABILITY, ).indicator, CommonServerPython.create_indicator_result_with_dbotscore_unknown( indicator="http://squirtle.com", indicator_type=CommonServerPython.DBotScoreType.URL, reliability=FortiSandboxv2.RELIABILITY, ).indicator, ], ), ], ) def test_url_command( requests_mock, mock_client: FortiSandboxv2.Client, file_name: str, expected_outputs: list[CommonServerPython.Common.Indicator], ): """Test the url_command function for generic reputation. Ensure: - The indicator is set to the expected indicator value. - The raw response is set to the expected raw response. Args: requests_mock (pytest_mock.plugin.MockerFixture): Mocked requests. mock_client (FortiSandboxv2.Client): Mocked client file_name (str): The file name for the mocked response. expected_outputs (list[CommonServerPython.Common.Indicator]): expected output for assertion. """ mock_response = load_mock_response(file_name) requests_mock.post(API_URL, json=mock_response) command_results = FortiSandboxv2.url_command(mock_client, {"url": "www.pokemon.com"}) for command_result, expected_output in zip(command_results, expected_outputs): assert command_result.indicator.to_context() == expected_output.to_context() assert command_result.raw_response == mock_response @pytest.mark.parametrize( "file_name,expected_outputs", [ ( "file_verdict_known.json", [ CommonServerPython.Common.File( dbot_score=CommonServerPython.Common.DBotScore( indicator="0000000000000000000000000000000000000000000000000000000000000000", indicator_type=CommonServerPython.DBotScoreType.FILE, score=CommonServerPython.Common.DBotScore.BAD, reliability=FortiSandboxv2.RELIABILITY, message="", ), sha256="0000000000000000000000000000000000000000000000000000000000000000", malware_family=["pokemon"], name="pikachu.exe", extension="exe", relationships=[ CommonServerPython.EntityRelationship( name=CommonServerPython.EntityRelationship.Relationships.INDICATOR_OF, entity_a="0000000000000000000000000000000000000000000000000000000000000000", entity_a_type=CommonServerPython.FeedIndicatorType.File, entity_b="pokemon", entity_b_type=CommonServerPython.FeedIndicatorType.Malware, reverse_name=CommonServerPython.EntityRelationship.Relationships.INDICATED_BY, brand="FortiSandbox", source_reliability=FortiSandboxv2.RELIABILITY, ) ], ), ], ), ( "file_verdict_unknown.json", [ CommonServerPython.create_indicator_result_with_dbotscore_unknown( indicator="0000000000000000000000000000000000000000000000000000000000000000", indicator_type=CommonServerPython.DBotScoreType.FILE, reliability=FortiSandboxv2.RELIABILITY, ).indicator, ], ), ], ) def test_file_command( requests_mock, mock_client: FortiSandboxv2.Client, file_name: str, expected_outputs: list[CommonServerPython.Common.Indicator], ): """Test the file_command function for generic reputation. Ensure: - The indicator is set to the expected indicator value. - The raw response is set to the expected raw response. Args: requests_mock (pytest_mock.plugin.MockerFixture): Mocked requests. mock_client (FortiSandboxv2.Client): Mocked client file_name (str | None): The file name for the mocked response. expected_outputs (list[CommonServerPython.Common.Indicator]): expected output for assertion. """ sha256 = "0000000000000000000000000000000000000000000000000000000000000000" mock_response = load_mock_response(file_name) requests_mock.post(API_URL, json=mock_response) command_results = FortiSandboxv2.file_command(mock_client, {"file": sha256}) for command_result, expected_output in zip(command_results, expected_outputs): assert command_result.indicator.to_context() == expected_output.to_context() assert command_result.raw_response == mock_response def test_submission_file_upload_command_error(mock_client: FortiSandboxv2.Client): """Test the submission_file_upload_command function with an error. Ensure: - A DemistoException is raised. Args: mock_client (FortiSandboxv2.Client): Mocked client. """ with pytest.raises(CommonServerPython.DemistoException): FortiSandboxv2.submission_file_upload_command({"comment": "0" * 256}, mock_client) @pytest.mark.parametrize( "args", [ ({"comment": "0" * 256}), ({"depth": "6"}), ({"process_timeout": "29"}), ], ) def test_submission_url_upload_command_error(mock_client: FortiSandboxv2.Client, args: dict[str, Any]): """Test the submission_url_upload_command function with an error. Ensure: - A DemistoException is raised. Args: mock_client (FortiSandboxv2.Client): Mocked client. args (dict[str, Any]): The arguments to pass to the function. """ with pytest.raises(CommonServerPython.DemistoException): FortiSandboxv2.submission_url_upload_command(args, mock_client) def test_submission_cancel_command(requests_mock, mock_client: FortiSandboxv2.Client): """Test the submission_cancel_command function. Ensure: - The readable output is set to the expected readable output. - The raw response is set to the expected raw response. Args: requests_mock (pytest_mock.plugin.MockerFixture): Mocked requests. mock_client (FortiSandboxv2.Client): Mocked client """ sid = "123" mock_raw_response = {"result": {"status": {"code": 0}}} requests_mock.post(API_URL, json=mock_raw_response) command_results = FortiSandboxv2.submission_cancel_command(mock_client, {"id": sid}) assert command_results.readable_output == f"## The cancellation of the submission {sid} was successfully sent." assert command_results.raw_response == mock_raw_response def test_submission_job_verdict_command(requests_mock, mock_client: FortiSandboxv2.Client): """Test the submission_job_verdict_command function. Ensure: - The command results is set to the expected command results value. Args: requests_mock (pytest_mock.plugin.MockerFixture): Mocked requests. mock_client (FortiSandboxv2.Client): Mocked client """ url = "www.pokemon.com" jid = "123" mock_raw_response = load_mock_response("job_verdict.json") indicator = CommonServerPython.Common.URL( dbot_score=CommonServerPython.Common.DBotScore( indicator=url, indicator_type=CommonServerPython.DBotScoreType.URL, score=CommonServerPython.Common.DBotScore.GOOD, reliability=FortiSandboxv2.RELIABILITY, message="https://pikachu/job-detail/?sid=456&jid=123&req_type=url-csearch", ), url=url, ) requests_mock.post(API_URL, json=mock_raw_response) command_results = FortiSandboxv2.submission_job_verdict_command(mock_client, {"id": jid}) mock_raw_response["result"]["data"]["name"] = url assert command_results.outputs_prefix == "FortiSandbox.Submission" assert command_results.outputs_key_field == "jid" assert command_results.outputs == {**mock_raw_response["result"]["data"], "name": url} assert command_results.readable_output.startswith(f"### The verdict for the job {jid}:") assert command_results.raw_response == mock_raw_response assert command_results.indicator.to_context() == indicator.to_context() def test_submission_job_list_command(requests_mock, mock_client: FortiSandboxv2.Client): """Test the submission_job_list_command function. Ensure: - The command results is set to the expected command results value. Args: requests_mock (pytest_mock.plugin.MockerFixture): Mocked requests. mock_client (FortiSandboxv2.Client): Mocked client """ sid = "123" mock_raw_response = load_mock_response("job_list_done.json") requests_mock.post(API_URL, json=mock_raw_response) command_results = FortiSandboxv2.submission_job_list_command(mock_client, {"id": sid}) assert command_results.outputs_prefix == "FortiSandbox.Submission" assert command_results.outputs_key_field == "jid" assert command_results.outputs == [{"sid": sid, "jid": jid} for jid in ["000", "111", "222"]] assert command_results.readable_output.startswith(f"### The submission {sid} job IDs:") assert command_results.raw_response == mock_raw_response @pytest.mark.parametrize( "identifier", ["123", "0000000000000000000000000000000000000000000000000000000000000000"], ) def test_submission_job_report_command(requests_mock, mock_client: FortiSandboxv2.Client, identifier: str): """Test the submission_job_report_command function. Ensure: - The file result is set to the expected file result value. - The file content is set to the expected file content value. Args: requests_mock (pytest_mock.plugin.MockerFixture): Mocked requests. mock_client (FortiSandboxv2.Client): Mocked client identifier (str): The identifier for the job. """ mock_raw_response = load_mock_response("job_report.json") requests_mock.post(API_URL, json=mock_raw_response) # Use mock_open to simulate file operations mock_open = unittest.mock.mock_open() with ( unittest.mock.patch("builtins.open", mock_open), unittest.mock.patch("FortiSandboxv2.demisto.uniqueFile", return_value="mock_file_id"), ): file_result = FortiSandboxv2.submission_job_report_command(mock_client, {"identifier": identifier}) handle = mock_open() assert file_result == { "Contents": "", "ContentsFormat": "text", "Type": CommonServerPython.EntryType.ENTRY_INFO_FILE, "File": "pikachu.pdf", "FileID": file_result["FileID"], } # Retrieve the write calls to the mock file and assert the content assert handle.write.call_args[0][0] == b"Decoded Pikachu" def test_is_url_by_ftype(): """Test URL detection using ftype field""" data = {"ftype": "WEBLink", "name": "not a url", "download_url": ""} assert is_url(data) is True def test_is_url_by_http_name(): """Test URL detection using http name field""" data = {"ftype": "File", "name": "http://example.com", "download_url": ""} assert is_url(data) is True def test_is_url_by_https_name(): """Test URL detection using https name field""" data = {"ftype": "File", "name": "https://example.com", "download_url": ""} assert is_url(data) is True def test_is_url_empty_data(): """Test with empty data""" assert is_url({}) is False def test_is_url_missing_fields(): """Test with missing fields""" data = { "name": "http://example.com" # Missing other fields } assert is_url(data) is True # Should still detect from name data = { "ftype": "File" # Only has ftype } assert is_url(data) is False def test_build_indicator_unknown_type(): """ Test the build_indicator function with unknown indicator type. Ensure: - A ValueError is raised when the indicator type cannot be determined. """ from FortiSandboxv2 import build_indicator # Test data that doesn't contain URL or file hash information test_data = { "score": 3, "malware_name": "test_malware", "detail_url": "https://example.com/detail?sid=123", "category": "test_category", } # The error message we expect to see expected_error = "Could not determine indicator type" # Verify that the function raises a ValueError with the expected message with pytest.raises(CommonServerPython.DemistoException) as exc_info: build_indicator(data=test_data, url=None, file_hash=None) # Check that the error message contains our expected text assert expected_error in str(exc_info.value)