MetaDefender Sandbox Deprecated
Deprecated. Use MetaDefender Aether instead.
Forensics & Malware Analysis · MetaDefender Sandbox (Deprecated)
Details
| ID | MetaDefender Sandbox |
|---|---|
| Provider | OPSWAT |
| Category | Forensics & Malware Analysis |
| From Version | 6.0.0 |
| Docker Image | demisto/python3:3.12.8.3296088 |
README
Unique adaptive threat analysis technology, enabling zero-day malware detection and more Indicator of Compromise (IOCs) extraction. (previously known as OPSWAT Filescan Sandbox)
Configure MetaDefender Sandbox in Cortex
| Parameter | Required |
|---|---|
| Server URL (e.g. https://www.filescan.io/api) | True |
| API Key | True |
| Trust any certificate (not secure) | False |
| Use system proxy settings | False |
| Verbose | False |
Commands
You can execute these commands from the 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.
metadefender-sandbox-scan-url
Scan URL with MetaDefender Sandbox
Note: MetaDefender Sandbox handles URL scanning as a file scan.
Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.
Base Command
metadefender-sandbox-scan-url
Input
| Argument Name | Description | Required |
|---|---|---|
| url | The URL to submit | Required |
| timeout | The timeout for the polling in seconds | Optional |
| hide_polling_output | Hide polling output | Optional |
| description | Uploaded file/url description | Optional |
| tags | Tags array to propagate | Optional |
| password | Custom password, in case uploaded archive is protected | Optional |
| is_private | If file should not be available for download by other users | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| 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. |
| File.Name | String | The full file name. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Malicious.Vendor | String | The vendor that reported the file as malicious. |
| MetaDefender.Sandbox.Analysis.finalVerdict.verdict | String | The final verdict. |
| MetaDefender.Sandbox.Analysis.allTags | Unknown | All tags. |
| MetaDefender.Sandbox.Analysis.overallState | String | Overall state of the scan. |
| MetaDefender.Sandbox.Analysis.taskReference.name | String | Name of the main scan task. |
| MetaDefender.Sandbox.Analysis.taskReference.additionalInfo | Unknown | Additional informations about the main scan task. |
| MetaDefender.Sandbox.Analysis.taskReference.ID | String | ID of the main scan task. |
| MetaDefender.Sandbox.Analysis.taskReference.state | String | State of the main scan task. |
| MetaDefender.Sandbox.Analysis.taskReference.resourceReference | Unknown | Resource reference of the main scan task. |
| MetaDefender.Sandbox.Analysis.taskReference.opcount | Number | Counter. |
| MetaDefender.Sandbox.Analysis.taskReference.processTime | Number | processTime. |
| MetaDefender.Sandbox.Analysis.subtaskReferences | Unknown | Status of scan subtasks. |
| MetaDefender.Sandbox.Analysis.allSignalGroups | Unknown | All signal groups. |
| MetaDefender.Sandbox.Analysis.resources | Unknown | Resources. |
| MetaDefender.Sandbox.Analysis.file.name | String | The name of the file. |
| MetaDefender.Sandbox.Analysis.file.hash | String | The SHA256 of the file. |
| MetaDefender.Sandbox.Analysis.file.type | String | The type of the submission. |
Command example
!metadefender-sandbox-scan-url url=https://www.test.com
Context Example
{
{
"DBotScore":
[
{
"Indicator": "1111111111111111111111111111111111111111111111111111111111111111",
"Score": 1,
"Type": "file",
"Vendor": "MetaDefender Sandbox"
}
],
"File":
[
{
"Name": "https://www.test.com",
"SHA256": "1111111111111111111111111111111111111111111111111111111111111111"
}
],
"MetaDefender":
{
"Sandbox":
{
"Analysis":
[
{
"finalVerdict":
{
"verdict": "BENIGN"
},
"allTags":
[
{
"source": "MEDIA_TYPE",
"sourceIdentifier": "12345678",
"isRootTag": true,
"tag":
{
"name": "html",
"synonyms":
[],
"descriptions":
[],
"verdict":
{
"verdict": "NO_THREAT",
"threatLevel": 0.1,
"confidence": 1
}
}
}
],
"overallState": "success_partial",
"taskReference":
{
"name": "transform-file",
"additionalInfo":
{
"submitName": "https://www.test.com",
"submitTime": 1679014774270,
"digests":
{
"SHA-256": "1111111111111111111111111111111111111111111111111111111111111111"
}
},
"ID": "abcd-1234",
"state": "SUCCESS",
"resourceReference":
{
"type": "TRANSFORM_FILE",
"name": "file",
"ID": "abcd-5678"
},
"opcount": 1,
"processTime": 20350
},
"subtaskReferences":
[
{
"name": "domain-resolve",
"additionalInfo": 72,
"ID": "12345678",
"state": "SUCCESS",
"resourceReference":
{
"type": "DOMAIN_RESOLVE",
"name": "domain-resolve",
"ID": "123456789"
},
"opcount": 20,
"processTime": 11309
}
],
"allSignalGroups":
[
{
"identifier": "I000",
"description": "OSINT source detected malicious resource",
"averageSignalStrength": 0.75,
"peakSignalStrength": 0.75,
"finalSignalStrength": 0.75,
"verdict":
{
"verdict": "LIKELY_MALICIOUS",
"threatLevel": 0.75,
"confidence": 1
},
"allTags":
[],
"signals":
[
{
"strength": 0.75,
"isStrictlyBasedOnInputData": false,
"signalReadable": "OSINT provider TEST provider (2/93)",
"additionalInfo": "https://www.google.com",
"originPath": "osint.results.verdict",
"originType": "INPUT_FILE",
"originIdentifier": "1234"
}
]
}
],
"resources":
{
"00f1e4d6-27fb-45e8-8a02-dc53818044ec":
{
"resourceReference":
{
"name": "osint"
},
"results":
[]
}
},
"file":
{
"name": "https://www.test.com",
"hash": "1111111111111111111111111111111111111111111111111111111111111111",
"type": "other"
}
}
]
}
}
}
Human Readable Output
Scan Result (digest)
FileHash FileName FileType FinalVerdict SubtaskReferences Tags 1111111111111111111111111111111111111111111111111111111111111111 https://www.test.com other BENIGN osint, url-render, domain-resolve html, png
metadefender-sandbox-scan-file
Scan File with MetaDefender Sandbox
Base Command
metadefender-sandbox-scan-file
Input
| Argument Name | Description | Required |
|---|---|---|
| entry_id | he War Room entry ID of the file to submit | Required |
| timeout | The timeout for the polling in seconds | Optional |
| hide_polling_output | Hide polling output | Optional |
| description | Uploaded file/url description | Optional |
| tags | Tags array to propagate | Optional |
| password | Custom password, in case uploaded archive is protected | Optional |
| is_private | If file should not be available for download by other users | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| 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. |
| File.Name | String | The full file name. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Malicious.Vendor | String | The vendor that reported the file as malicious. |
| MetaDefender.Sandbox.Analysis.finalVerdict.verdict | String | The final verdict. |
| MetaDefender.Sandbox.Analysis.allTags | Unknown | All tags. |
| MetaDefender.Sandbox.Analysis.overallState | String | Overall state of the scan. |
| MetaDefender.Sandbox.Analysis.taskReference.name | String | Name of the main scan task. |
| MetaDefender.Sandbox.Analysis.taskReference.additionalInfo | Unknown | Additional informations about the main scan task. |
| MetaDefender.Sandbox.Analysis.taskReference.ID | String | ID of the main scan task. |
| MetaDefender.Sandbox.Analysis.taskReference.state | String | State of the main scan task. |
| MetaDefender.Sandbox.Analysis.taskReference.resourceReference | Unknown | Resource reference of the main scan task. |
| MetaDefender.Sandbox.Analysis.taskReference.opcount | Number | Counter. |
| MetaDefender.Sandbox.Analysis.taskReference.processTime | Number | processTime. |
| MetaDefender.Sandbox.Analysis.subtaskReferences | Unknown | Status of scan subtasks. |
| MetaDefender.Sandbox.Analysis.allSignalGroups | Unknown | All signal groups. |
| MetaDefender.Sandbox.Analysis.resources | Unknown | Resources. |
| MetaDefender.Sandbox.Analysis.file.name | String | The name of the file. |
| MetaDefender.Sandbox.Analysis.file.hash | String | The SHA256 of the file. |
| MetaDefender.Sandbox.Analysis.file.type | String | The type of the submission. |
Command example
!metadefender-sandbox-scan-file entry_id=1234@abcd-efgh-ijkl-mnop-xyz
Context Example
{
{
"DBotScore":
[
{
"Indicator": "1111111111111111111111111111111111111111111111111111111111111111",
"Score": 1,
"Type": "file",
"Vendor": "MetaDefender Sandbox"
}
],
"File":
[
{
"Name": "1234@abcd-efgh-ijkl-mnop-xyz",
"SHA256": "1111111111111111111111111111111111111111111111111111111111111111"
}
],
"MetaDefender":
{
"Sandbox":
{
"Analysis":
[
{
"finalVerdict":
{
"verdict": "MALICIOUS"
},
"allTags":
[
{
"source": "SIGNAL",
"sourceIdentifier": "1234",
"isRootTag": false,
"tag":
{
"name": "packed",
"synonyms": [],
"descriptions": [],
"verdict": {
"verdict": "SUSPICIOUS",
"threatLevel": 0.5,
"confidence": 1
}
}
}
],
"overallState": "success_partial",
"taskReference":
{
"name": "transform-file",
"additionalInfo": {
"submitName": "bad_file.exe",
"submitTime": 1679011634945,
"digests": {
"SHA-256": "1111111111111111111111111111111111111111111111111111111111111111"
}
},
"ID": "1234",
"state": "SUCCESS",
"resourceReference": {
"type": "TRANSFORM_FILE",
"name": "file",
"ID": "0101010101"
},
"opcount": 1,
"processTime": 7180
},
"subtaskReferences":
[
{
"name": "domain-resolve",
"additionalInfo": 72,
"ID": "12345678",
"state": "SUCCESS",
"resourceReference":
{
"type": "DOMAIN_RESOLVE",
"name": "domain-resolve",
"ID": "123456789"
},
"opcount": 20,
"processTime": 11309
}
],
"allSignalGroups":
[
{
"identifier": "Y002",
"description": "Matched a malicious YARA rule",
"averageSignalStrength": 1,
"peakSignalStrength": 1,
"finalSignalStrength": 1,
"verdict": {
"verdict": "MALICIOUS",
"threatLevel": 1,
"confidence": 1
},
"allTags": [],
"signals": [
{
"strength": 1,
"isStrictlyBasedOnInputData": true,
"signalReadable": "Matched YARA with strength \"0.75\"",
"additionalInfo": "PUP_InstallRex_AntiFWb",
"originPath": "file.yaraMatches",
"originType": "INPUT_FILE",
"originIdentifier": "111111111111111111111111111"
}
]
}
],
"resources":
{
"00f1e4d6-27fb-45e8-8a02-dc53818044ec":
{
"resourceReference":
{
"name": "osint"
},
"results":
[]
}
},
"file":
{
"name": "1234@abcd-efgh-ijkl-mnop-xyz",
"hash": "1111111111111111111111111111111111111111111111111111111111111111",
"type": "other"
}
}
]
}
}
}
Human Readable Output
Scan Result (digest)
FileHash FileName FileType FinalVerdict SubtaskReferences Tags 1111111111111111111111111111111111111111111111111111111111111111 1234@abcd-efgh-ijkl-mnop-xyz pe MALICIOUS visualization, osint, domain-resolve html, peexe
metadefender-sandbox-search-query
Search for reports. Finds reports and uploaded files by various tokens.
Base Command
metadefender-sandbox-search-query
Input
| Argument Name | Description | Required |
|---|---|---|
| query | The query string | Required |
| limit | Number of total results. Maximum 50 | Optional |
| page | Page number, starting from 1 | Optional |
| page_size | The page size. Can be 5, 10 or 20 | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MetaDefender.Sandbox.Analysis.id | String | The analysis id. |
| MetaDefender.Sandbox.Analysis.file.name | String | The name of the file. |
| MetaDefender.Sandbox.Analysis.file.sha256 | String | The SHA256 of the file. |
| MetaDefender.Sandbox.Analysis.verdict | String | The final verdict. |
| MetaDefender.Sandbox.Analysis.state | String | Overall state of the scan. |
| MetaDefender.Sandbox.Analysis.date | Date | The scan date. |
| MetaDefender.Sandbox.Analysis.file.mime_type | String | The file MimeType. |
| MetaDefender.Sandbox.Analysis.file.short_type | String | The type of the submission. |
| MetaDefender.Sandbox.Analysis.tags | Unknown | All tags. |
Command example
!metadefender-sandbox-search-query query="834d1dbfab8330ea5f1844f6e905ed0ac19d1033ee9a9f1122ad2051c56783dc"
Context Example
{
"MetaDefender":
{
"Sandbox":
{
"Analysis":
[
{
"id": "b4f92c03-0fc2-4a40-9d34-8f2b05dd240c",
"file": {
"name": "bad_file.exe",
"mime_type": "application/x-msdownload",
"short_type": "peexe",
"sha256": "834d1dbfab8330ea5f1844f6e905ed0ac19d1033ee9a9f1122ad2051c56783dc",
},
"state": "success",
"verdict": "malicious",
"tags": [
{
"source": "MEDIA_TYPE",
"sourceIdentifier": "834d1dbfab8330ea5f1844f6e905ed0ac19d1033ee9a9f1122ad2051c56783dc",
"isRootTag": true,
"tag": {
"name": "peexe",
"synonyms": [],
"descriptions": [],
"verdict": {
"verdict": "NO_THREAT",
"threatLevel": 0.1,
"confidence": 1
}
}
}
],
"date": "03/20/2023, 14:28:09"
}
]
}
}
}
Human Readable Output
Analysis Result
Id SampleName SHA256 Verdict State Date 8c38be8c-7cfd-4d64-be41-c98a795c9ce0 bad_file.exe 834d1dbfab8330ea5f1844f6e905ed0ac19d1033ee9a9f1122ad2051c56783dc MALICIOUS success_partial 03/14/2023, 15:07:07 e334d27f-e2b1-46c9-9936-7d3155eb3706 bad_file.exe 834d1dbfab8330ea5f1844f6e905ed0ac19d1033ee9a9f1122ad2051c56783dc UNKNOWN success 03/14/2020, 15:03:48
Configuration parameters
url— Server URL (e.g. https://www.filescan.io/api) (required)api_key— (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (3)
-
metadefender-sandbox-scan-fileScan file resource.
-
metadefender-sandbox-scan-urlScan URL resource.
-
metadefender-sandbox-search-querySearch for reports. Finds reports and uploaded files by various tokens.
from CommonServerPython import * from CommonServerUserPython import * """ IMPORTS """ from typing import Any import urllib3 # Disable insecure warnings urllib3.disable_warnings() """GLOBALS/PARAMS """ INTEGRATION_NAME = "MetaDefender Sandbox Integration" INTEGRATION_CONTEXT_NAME = "MetaDefender.Sandbox" class Client(BaseClient): def __init__(self, api_key: str, base_url: str, proxy: bool, verify: bool): super().__init__(base_url=base_url, proxy=proxy, verify=verify) self.api_key = api_key if self.api_key: self._headers = {"X-Api-Key": self.api_key} def test_module(self) -> dict: """ Return information about the user. (Need API key) """ request_result = self._http_request( method="GET", ok_codes=([200]), url_suffix="/users/me", ) return request_result def post_sample(self, args: dict[str, Any]) -> dict[str, Any]: data = {} if description := args.get("description"): data["description"] = description if tags := args.get("tags"): data["tags"] = tags if password := args.get("password"): data["password"] = password if is_private := args.get("is_private"): data["is_private"] = is_private if url := args.get("url"): data["url"] = url return self._http_request(method="POST", url_suffix="/scan/url", ok_codes=([200]), data=data) elif entry_id := args.get("entry_id"): try: file_entry = demisto.getFilePath(entry_id) except Exception as e: raise DemistoException(f'Failed to find file entry with id:"{entry_id}". got error: {e}') with open(file_entry["path"], "rb") as file: return self._http_request( method="POST", url_suffix="/scan/file", ok_codes=([200]), data=data, files={"file": file}, ) else: raise DemistoException("No file or URL was provided.") def get_scan_result(self, flow_id: str) -> dict[str, Any]: filters = [ "filter=general", "filter=finalVerdict", "filter=allTags", "filter=overallState", "filter=taskReference", "filter=subtaskReferences", "filter=allSignalGroups", ] postfix = "&".join(filters) url_suffix = f"/scan/{flow_id}/report?{postfix}" response = self._http_request( method="GET", ok_codes=([200]), url_suffix=url_suffix, ) return response def get_search_query(self, query_string: str, page: int, page_size: int) -> dict[str, Any]: return self._http_request( method="GET", ok_codes=([200]), params={"query": query_string, "page_size": page_size, "page": page}, url_suffix="/reports/search", ) """ HELPER FUNCTIONS """ def build_one_reputation_result(report: dict[str, Any]): score = Common.DBotScore.NONE final_verdict = report.get("finalVerdict", {}) verdict = final_verdict.get("verdict") if verdict.upper() == "BENIGN" or verdict.upper() == "INFORMATIONAL" or verdict.upper() == "NO_THREAT": score = Common.DBotScore.GOOD elif verdict.upper() == "MALICIOUS" or verdict.upper() == "LIKELY_MALICIOUS": score = Common.DBotScore.BAD elif verdict.upper() == "SUSPICIOUS": score = Common.DBotScore.SUSPICIOUS report_file = report.get("file", {}) report_hash = report_file.get("hash", None) dbot_score = Common.DBotScore( indicator=report_hash, indicator_type=DBotScoreType.FILE, integration_name="MetaDefender Sandbox", score=score, ) file = Common.File(name=report_file.get("name"), sha256=report_hash, dbot_score=dbot_score) tags = [tag.get("tag", {}).get("name") for tag in report.get("allTags", [])] subtasks = [subtask.get("name") for subtask in report.get("subtaskReferences", [])] human_readable = { "FileName": report_file.get("name"), "FileHash": report_hash, "FileType": report_file.get("type"), "FinalVerdict": report.get("finalVerdict", {}).get("verdict"), "Tags": tags, "SubtaskReferences": subtasks, } readable_output = tableToMarkdown("Scan Result (digest):", human_readable) results = CommandResults( outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.Analysis", outputs_key_field="sha256", outputs=report, raw_response=report, readable_output=readable_output, indicator=file, ) return results def build_serach_query_result(analyses: list[dict]) -> CommandResults: def build_analysis_hr(analysis: dict[str, Any]) -> dict[str, Any]: file_result = analysis.get("file", {}) hr_analysis = { "Id": analysis.get("id"), "SampleName": file_result.get("name"), "SHA256": file_result.get("sha256"), "Verdict": analysis.get("verdict"), "State": analysis.get("state"), "Date": analysis.get("date"), "MIMEType": file_result.get("mime_type"), "Type": file_result.get("short_type"), "Tags": analysis.get("tags"), } return hr_analysis def build_indicator_object(analysis: dict[str, Any]): score = Common.DBotScore.NONE verdict = analysis.get("verdict", "UNKNOWN") if verdict.upper() == "BENIGN" or verdict.upper() == "INFORMATIONAL" or verdict.upper() == "NO_THREAT": score = Common.DBotScore.GOOD elif verdict.upper() == "MALICIOUS" or verdict.upper() == "LIKELY_MALICIOUS": score = Common.DBotScore.BAD elif verdict.upper() == "SUSPICIOUS": score = Common.DBotScore.SUSPICIOUS analysis_file = analysis.get("file", {}) dbot_score = Common.DBotScore( indicator=analysis_file.get("sha256"), indicator_type=DBotScoreType.FILE, integration_name="MetaDefender Sandbox", score=score, ) file = Common.File( name=analysis_file.get("name"), sha256=analysis_file.get("sha256"), dbot_score=dbot_score, ) results = CommandResults( outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.Analysis", outputs_key_field="sha256", indicator=file, ) return results hr_headers = [ "Id", "SampleName", "SHA256", "Verdict", "State", "Date", "MIMEType", "Type", "Tags", ] hr_analysis_ls = [] for analysis in analyses: hr_analysis_ls.append(build_analysis_hr(analysis)) command_result = CommandResults( outputs=analyses, readable_output=tableToMarkdown("Analysis Result:", hr_analysis_ls, hr_headers), outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.Analysis", ) return command_result def sample_submission(client: Client, args: dict[str, Any]) -> PollResult: res = client.post_sample(args) partial_res = CommandResults(readable_output=f'Waiting for submission "{res.get("flow_id")}" to finish...') return PollResult( response=CommandResults( outputs=res, outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.Submission", outputs_key_field="flow_id", ), args_for_next_run={"flow_id": res.get("flow_id"), **args}, continue_to_poll=True, partial_result=partial_res, ) def build_reputation_result(api_reponse: dict[str, Any]): reports = api_reponse.get("reports", []) command_res_ls = [] for report in reports: command_res_ls.append(build_one_reputation_result(reports[report])) return command_res_ls def is_valid_pass(api_response: dict[str, Any]): if "rejected_files" not in api_response: return True return all(reject.get("rejected_reason") != "INVALID_PASSWORD" for reject in api_response["rejected_files"]) @polling_function( name=demisto.command(), timeout=arg_to_number(demisto.args().get("timeout", 600)), interval=1, poll_message="Polling result", requires_polling_arg=False, ) def polling_submit_command(args: dict[str, Any], client: Client): if flow_id := args.get("flow_id"): api_response = client.get_scan_result(flow_id) successful_response = False if api_response.get("allFinished", False): successful_response = True if successful_response: if not is_valid_pass(api_response): raise DemistoException("Invalid password!") return PollResult(response=build_reputation_result(api_response), continue_to_poll=False) return PollResult( response=[ CommandResults( outputs=api_response, outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.Submission", outputs_key_field="flow_id", readable_output=f'Waiting for submission "{api_response.get("flow_id")}" to finish...', ), ], continue_to_poll=True, args_for_next_run={"flow_id": args.get("flow_id"), **args}, ) else: return sample_submission(client, args) """ COMMANDS """ def test_module_command(client: Client, *_) -> str: """Performs a basic GET request to check if the API is reachable and authentication is successful.""" results = client.test_module() if "accountId" in results: return "ok" raise DemistoException(f"\nTest module failed, {results}") def scan_command(client: Client, args: dict[str, Any]): return polling_submit_command(args=args, client=client) def search_query_command(client: Client, args: dict[str, Any]): def validate_args(): if page_size and page_size not in [5, 10, 20]: raise DemistoException("Page size value must be 5, 10 or 20") if page and page <= 0: raise DemistoException("Page must be an integer and grater than 0") if limit and (limit <= 0 or limit > 50): raise DemistoException("Limit must be an integer and between 1 and 50") items = [] query_string = args.get("query", "") page_size = arg_to_number(args.get("page_size")) page = arg_to_number(args.get("page")) limit = arg_to_number(args.get("limit")) or 10 validate_args() if page_size and not page: page = 1 elif not page_size and page: page_size = 10 if page_size and page: items = client.get_search_query(query_string, page, page_size).get("items", []) else: page_size = 20 page = 1 continue_query = True while continue_query: response = client.get_search_query(query_string, page, page_size) actual_items = response.get("items", []) total_available_items = response.get("count", len(items)) # queried all or reached the limit if total_available_items == len(items) or len(items) >= limit: continue_query = False items += actual_items page += 1 items = items[0:limit] if items: return build_serach_query_result(items) return CommandResults(readable_output="No Results were found.") """ COMMANDS MANAGER / SWITCH PANEL """ def main(): params = demisto.params() base_url = params.get("url", "") api_key = params.get("api_key", {}).get("password") verify = not params.get("insecure", False) proxy = params.get("proxy", False) command = demisto.command() demisto.info(f"Command being called is {command}") args = demisto.args() try: client = Client(api_key=api_key, base_url=base_url, verify=verify, proxy=proxy) handle_proxy() if command == "test-module": return_results(test_module_command(client)) elif command == "metadefender-sandbox-scan-url": return_results(scan_command(client, args)) elif command == "metadefender-sandbox-scan-file": return_results(scan_command(client, args)) elif command == "metadefender-sandbox-search-query": return_results(search_query_command(client, args)) else: raise NotImplementedError(f"{command} command is not implemented.") except Exception as e: err_msg = f"Exception in {INTEGRATION_NAME} : Failed to execute {command} command: [{e!r}]" return_error(err_msg, error=e) """ ENTRY POINT """ if __name__ in ("__main__", "__builtin__", "builtins"): main()