rapid7_threat_command

Rapid7 Insight - Threat Command allows managing alerts, CVEs, IOCs, and assets by accounts and MSSP accounts.

Network Security · Rapid7 - Threat Command (IntSights)

Details

IDrapid7_threat_command
ProviderRapid7
CategoryNetwork Security
From Version6.8.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

Rapid7 Insight - Threat Command allows managing alerts, CVEs, IOCs, and assets by accounts and MSSP accounts.
This integration was integrated and tested with version 3.1.4 of rapid7_threat_command

Configure Rapid7 - Threat Command (IntSights) in Cortex

Parameter Description Required
Server URL URL of the Rapid7 platform. True
Account ID   True
API key   True
Source Reliability Reliability of the source providing the intelligence data. True
Fetch incidents   False
First fetch timestamp. Timestamp in ISO format or <number> <time unit>, e.g., 2023-01-01T00:00:00.000Z, 12 hours, 7 days, 3 months, now. False
Maximum incidents per fetch The maximum number of alerts to fetch each time. The default is 50. If the value is greater than 200, it will be considered as 200. True
Alert types to fetch as incidents Alert types to fetch as incidents. False
Network types to fetch as incidents Network types to fetch as incidents. False
Minimum Alert Severity Level Alerts with the minimum level of severity to fetch. False
Source types to filter alerts by Source types to filter alerts by. False
Fetch closed alerts Fetch closed alerts from Rapid7 platform. False
Include CSV files of alerts   False
Include attachments of alerts MSSP accounts must provide a sub-account ID to perform this action. False
Sub-account ID (for MSSP accounts).   False
Incident type   False
Use system proxy settings   False
Trust any certificate (not secure)   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.

threat-command-cyber-term-list


List cyber terms by filter.

Base Command

threat-command-cyber-term-list

Input

Argument Name Description Required
search Filter by free text, which can be the cyber term name or ID. Optional
types A comma-separated list of cyber term types by which to filter the results. For example: ThreatActor,Campaign. Possible values are: Threat Actor, Malware, Campaign. Optional
severities A comma-separated list of cyber term severities by which to filter the results. For example: High,Low. Possible values are: High, Medium, Low. Optional
sectors A comma-separated list of targeted sectors by which to filter the results. For example: Education,Government. Optional
countries A comma-separated list of targeted countries by which to filter the results. For example: Albania,Algeria. Optional
origins A comma-separated list of nationalities by which to filter the results. For example: Egypt,Iraq. Optional
ttps A comma-separated list of TTPs by which to filter the results. For example: Malware,Backdoor. Optional
last_update_from Filter for results whose last update date is greater than the given value (in ISO 8601 format). For example: 2022-12-25T08:38:06Z. Default value: Last year. Optional
last_update_to Filter for results whose last update date is less than the given value (in ISO 8601 format). For example: 2022-12-25T08:38:06Z. Optional
page The page number of the results to retrieve (1-based). Default is 1. Optional
page_size The number of objects per page. Optional
limit The maximum number of records to retrieve. Default is 50. Optional

Context Output

Path Type Description
ThreatCommand.CyberTerm.id String The ID of the cyber term.
ThreatCommand.CyberTerm.type String The type of the cyber term.
ThreatCommand.CyberTerm.name String Name of the cyber term.
ThreatCommand.CyberTerm.severity String The severity of the cyber term.
ThreatCommand.CyberTerm.aliases String Aliases of the cyber term.
ThreatCommand.CyberTerm.target_countries String List of targeted countries.
ThreatCommand.CyberTerm.sectors String List of targeted sectors.
ThreatCommand.CyberTerm.origins String List of origin nationalities.
ThreatCommand.CyberTerm.created_date Date The date the cyber term was first reported.
ThreatCommand.CyberTerm.updated_date Date The date the cyber term was last updated.
ThreatCommand.CyberTerm.ttp String List of TTPs.
ThreatCommand.CyberTerm.overview String Overview of the cyber term.
ThreatCommand.CyberTerm.additional_information String Additional information about the cyber term.
ThreatCommand.CyberTerm.related_malware String Related malware names.
ThreatCommand.CyberTerm.related_threat_actor String Related threat actor names.
ThreatCommand.CyberTerm.related_campaigns String Related campaign names.
ThreatCommand.CyberTerm.MitreAttack.tactic String MITRE ATT&CK tactic name related to the cyber term.
ThreatCommand.CyberTerm.MitreAttack.Techniques.name String MITRE ATT&CK technique names.
ThreatCommand.CyberTerm.MitreAttack.Techniques.url String MITRE ATT&CK technique URLs.

Command example

!threat-command-cyber-term-list limit=1

Context Example

{
    "ThreatCommand": {
        "CyberTerm": {
            "MitreAttack": [],
            "additional_information": "N/A",
            "aliases": [],
            "created_date": "2022-05-09T08:57:28.920Z",
            "id": "6278d77884709631217f2ead",
            "name": "Curious Gorge",
            "origins": [
                "China"
            ],
            "overview": "The Curious Gorge threat group was first reported by Google's Threat Analysis Group (TAG) in March 2022, amidst the Russo-Ukrainian War. The APT group, attributed to China’s Liberation Army Strategic Support Force (PLA SSF), targets government, military, logistics, and manufacturing organizations in Ukraine, Russia, and Central Asia. There is little information about Curious Gorge’s TTPs. \n\nIn March 2022, Curious Gorge was observed targeting government and military organizations in Ukraine, Russia, Kazakhstan, and Mongolia. \n\nIn May 2022, Google reported that Curious Gorge attacked multiple government organizations in Russia, including the Ministry of Test Affairs as well as Russian defense contractors, manufacturers, and a logistics company. \n\nThe attacks of a Chinese state-sponsored group against Russian entities are interesting, as the two countries are allies. It may reflect a possible shift in China's intelligence collection objectives amidst the Russo-Ukrainian War.",
            "related_campaigns": [
                "The 2022 Russia-Ukraine Cyberwarfare"
            ],
            "related_malware": [],
            "related_threat_actor": [],
            "sectors": [
                "Aerospace/Defense",
                "Government",
                "Manufacturing"
            ],
            "severity": "Medium",
            "target_countries": [
                "Kazakhstan",
                "Mongolia",
                "Russian Federation",
                "Ukraine"
            ],
            "ttp": [],
            "type": "ThreatActor",
            "updated_date": "2022-05-09T09:04:11.589Z"
        }
    }
}

Human Readable Output

Cyber terms

Id Name Severity Overview Target Countries Sectors Related Campaigns
6278d77884709631217f2ead Curious Gorge Medium The Curious Gorge threat group was first reported by Google’s Threat Analysis Group (TAG) in March 2022, amidst the Russo-Ukrainian War. The APT group, attributed to China’s Liberation Army Strategic Support Force (PLA SSF), targets government, military, logistics, and manufacturing organizations in Ukraine, Russia, and Central Asia. There is little information about Curious Gorge’s TTPs.

In March 2022, Curious Gorge was observed targeting government and military organizations in Ukraine, Russia, Kazakhstan, and Mongolia.

In May 2022, Google reported that Curious Gorge attacked multiple government organizations in Russia, including the Ministry of Test Affairs as well as Russian defense contractors, manufacturers, and a logistics company.

The attacks of a Chinese state-sponsored group against Russian entities are interesting, as the two countries are allies. It may reflect a possible shift in China’s intelligence collection objectives amidst the Russo-Ukrainian War.
Kazakhstan,
Mongolia,
Russian Federation,
Ukraine
Aerospace/Defense,
Government,
Manufacturing
The 2022 Russia-Ukraine Cyberwarfare

threat-command-cyber-term-cve-list


List cyber term CVEs by cyber term ID.

Base Command

threat-command-cyber-term-cve-list

Input

Argument Name Description Required
cyber_term_id Cyber term unique ID (dependencies - use threat-command-cyber-term-list command to get all the cyber term IDs). Required
limit The maximum number of records to retrieve. Default is 50. Optional
all_results Show all results if True. Possible values are: true, false. Optional

Context Output

Path Type Description
ThreatCommand.CVE.id String CVE ID.
ThreatCommand.CVE.publish_date String CVE publish date.
ThreatCommand.CVE.vendor_product Number CVE vendor product.

Command example

!threat-command-cyber-term-cve-list cyber_term_id=1234 limit=1

Context Example

{
    "ThreatCommand": {
        "CVE": {
            "id": "CVE-2015-8562",
            "publish_date": "2015-12-16T21:59:00.000Z",
            "vendor_product": [
                "Joomla Joomla\\!"
            ]
        }
    }
}

Human Readable Output

Related CVEs to Cyber term 628223a9b8a7a90f3aca3d7d

Id Publish Date Vendor Product
CVE-2015-8562 2015-12-16T21:59:00.000Z Joomla Joomla!

threat-command-cyber-term-ioc-list


List cyber term IOCs by cyber term ID.

Base Command

threat-command-cyber-term-ioc-list

Input

Argument Name Description Required
cyber_term_id Cyber term unique ID (dependencies - use threat-command-cyber-term-list command to get all the cyber term IDs). Required
ioc_type IOC types to include. Possible values are: Ip Addresses, Urls, Domains, Hashes, Emails. Optional
page The page number of the results to retrieve (1-based). Default is 1. Optional
page_size The number of objects per page. Optional
limit The maximum number of records to retrieve. Default is 50. Optional

Context Output

Path Type Description
ThreatCommand.IOC.value String The value of the IOC.
ThreatCommand.IOC.type String The type of the IOC.
ThreatCommand.IOC.updated_date String The date the IOC was last updated.
ThreatCommand.IOC.status String The status of the IOC.
ThreatCommand.IOC.is_whitelisted String Whether the IOC is whitelisted.
ThreatCommand.IOC.severity String The severity of the IOC.
ThreatCommand.IOC.reporting_feeds String List of reporting feeds in which the value appears.

Command example

!threat-command-cyber-term-ioc-list cyber_term_id=1234 limit=1

Context Example

{
    "ThreatCommand": {
        "IOC": {
            "is_whitelisted": false,
            "reporting_feeds": [
                "Threat Library",
                "AlienVault OTX"
            ],
            "severity": "Medium",
            "status": "Active",
            "type": "Hashes",
            "updated_date": "2022-11-17T11:13:28.000Z",
            "value": "11bd2c9f9e2397c9a16e0990e4ed2cf0679498fe0fd418a3dfdac60b5c160ee5"
        }
    }
}

Human Readable Output

Related IOCs to Cyber term 628223a9b8a7a90f3aca3d7d

Value Type Is Whitelisted Updated Date
11bd2c9f9e2397c9a16e0990e4ed2cf0679498fe0fd418a3dfdac60b5c160ee5 Hashes false 2022-11-17T11:13:28.000Z

threat-command-source-list


Gets lists of IOC document sources.

Base Command

threat-command-source-list

Input

Argument Name Description Required
limit The maximum number of records to retrieve. Default is 50. Optional
all_results Show all results if True. Possible values are: true, false. Optional

Context Output

Path Type Description
ThreatCommand.Source.id String Source ID.
ThreatCommand.Source.name String Source name.
ThreatCommand.Source.confidence_level Number Source confidence level.
ThreatCommand.Source.is_enable Boolean Whether the source is enabled.
ThreatCommand.Source.type String Source type.

Command example

!threat-command-source-list limit=1

Context Example

{
    "ThreatCommand": {
        "Source": {
            "confidence_level": 3,
            "id": "5b68306cf84f7c8696047fda",
            "is_enabled": true,
            "name": "AlienVault OTX",
            "type": "IntelligenceFeed"
        }
    }
}

Human Readable Output

IOC sources

Id Name Confidence Level Type
5b68306cf84f7c8696047fda AlienVault OTX 3 IntelligenceFeed

threat-command-source-document-create


Adds a new IOC source document. At least one IOC is required.

Base Command

threat-command-source-document-create

Input

Argument Name Description Required
name Source name. Required
description Source description. Required
confidence_level Source confidence level. Possible values are: 1, 2, 3. Required
share Whether to share this source with all tenants (available for MSSP users only). Possible values are: true, false. Optional
severity Source severity level. Possible values are: High, Medium, Low. Optional
tags Comma-separated list of user tags for the document. Optional
domains Comma-separated list of domain IOC values to add. For example: securitywap.com,test.com. Optional
urls Comma-separated list of URL IOC values to add. For example: “http://securitywap.com/path”. Optional
ips Comma-separated list of IP IOC values to add. For example: 8.8.8.8,1.2.3.4. Optional
hashes Comma-separated list of hash IOC values to add. For example: 8100f3d2668f0f61e6c7ea0dfda59458111238dfeeb9bf47d9fa7543abfb6fb7. Optional
emails Comma-separated list of email IOC values to add. For example: test@test.com. Optional

Context Output

Path Type Description
ThreatCommand.Source.Files.id String Document source ID.
ThreatCommand.Source.Files.name String Document source name.

Command example

!threat-command-source-document-create name=2023test description=test confidence_level=1 domains=test.com

Context Example

{
    "ThreatCommand": {
        "Source": {
            "Files": {
                "id": "64538007a44a2f2d6740f6be",
                "name": "2023test"
            }
        }
    }
}

Human Readable Output

Source document successfully created

Id Name
64538007a44a2f2d6740f6be 2023test

threat-command-source-document-delete


Deletes an existing IOC source document.

Base Command

threat-command-source-document-delete

Input

Argument Name Description Required
source_id The ID of the source document (dependencies - use threat-command-source-ioc-get command with source_type=”Files” to get all the document source IDs). Required

Context Output

There is no context output for this command.

Command example

!threat-command-source-document-delete source_id=6400a3289083fa5eab401cdd

Human Readable Output

Source document “6400a3289083fa5eab401cdd” successfully deleted.

threat-command-source-document-ioc-create


Create new IOCs to existing IOC source documents. At least one IOC is required.

Base Command

threat-command-source-document-ioc-create

Input

Argument Name Description Required
source_id The ID of the source document (dependencies - use threat-command-source-ioc-get command with source_type=”Files” to get all the document source IDs). Required
domains Comma-separated list of domain IOC values to create. For example: securitywap.com,test.com. Optional
urls Comma-separated list of URL IOC values to create. For example: “http://securitywap.com/path”. Optional
ips Comma-separated list of IP IOC values to create. For example: 8.8.8.8,1.2.3.4. Optional
hashes Comma-separated list of hash IOC values to create. For example: 8100f3d2668f0f61e6c7ea0dfda59458111238dfeeb9bf47d9fa7543abfb6fb7. Optional
emails Comma-separated list of email IOC values to create. For example: test@test.com. Optional

Context Output

There is no context output for this command.

Command example

!threat-command-source-document-ioc-create source_id=6400a3289083fa5eab401cdd domains=test.com

Human Readable Output

IOC “[‘test.com’]” successfully added to “6400a3289083fa5eab401cdd” document source.

threat-command-ioc-search


Gets IOC details by value or IOC’s full enrichment data. While using the enrichment flag, the command is scheduled and allows us to get full enrichment data. Note that enrichment has a quota. You can get the quota by using threat-command-quotas-usage-get.

Base Command

threat-command-ioc-search

Input

Argument Name Description Required
ioc_value IOC value. Required when last_updated_from is not selected. Not supported for email addresses. While using this argument, all the other filtering arguments are not relevant. . Optional
page The page number of the results to retrieve (1-based). Default is 1. Optional
page_size The number of objects per page. Optional
limit The maximum number of records to retrieve. Default is 50. Optional
enrichment Enrichment flag. Use True to enrich the data about the IOC. Supported IOC types are: Domains, URLs, IP addresses and file hashes. While using this argument, all the other filtering arguments are not relevant (except ioc_value). . Possible values are: true, false. Optional
interval_in_seconds The interval in seconds between each poll. Relevant while enrichment=true. Default is 30. Optional
timeout_in_seconds The timeout in seconds until polling ends. Relevant while enrichment=true. Default is 600. Optional
last_updated_from Filter by last update date (IOC update date is greater than). For example: 2022-12-25T08:38:06Z. Required when ioc_value is not selected. Optional
last_updated_to Filter by last update date (IOC update date is less than). For example: 2022-12-25T08:38:06Z. Optional
last_seen_from Filter by last seen date (IOC last seen date is greater than). For example: 2022-12-25T08:38:06Z. Optional
last_seen_to Filter by last seen date (IOC last seen date is less than). For example: 2022-12-25T08:38:06Z. Optional
first_seen_from Filter by first seen date (IOC first seen date is greater than). For example: 2022-12-25T08:38:06Z. Optional
first_seen_to Filter by first seen date (IOC first seen date is less than). For example: 2022-12-25T08:38:06Z. Optional
status Filter by IOC status. Possible values are: Active, Retired. Optional
type_list Comma-separated list of IOC types to filter. For example: Urls,Domains. Possible values are: Ip Addresses, Urls, Domains, Hashes, Emails. Optional
severity_list Comma-separated list of IOC severities to filter. For example: Low,Medium. Possible values are: High, Medium, Low. Optional
whitelisted Filter by whitelist status. Possible values are: true, false. Optional
source_ids Comma-separated list of source IDs (dependencies - use threat-command-source-document-ioc-get command to get all the document source IDs). Optional
kill_chain_phases Comma-separated list of the phase of the Lockheed-Martin kills chain. For example: Delivery,Exploitation. Possible values are: Reconnaissance, Weaponization, Delivery, Exploitation, Installation, Command and Control, Actions on Objective. Optional

Context Output

Path Type Description
ThreatCommand.IOC.value String IOC value.
ThreatCommand.IOC.type String IOC type.
ThreatCommand.IOC.Source.name String IOC source name (Relevant to enrichment only).
ThreatCommand.IOC.Source.confindece_level String IOC source confidence level(Relevant to enrichment only).
ThreatCommand.IOC.system_tags String IOC system tags (Relevant to enrichment only).
ThreatCommand.IOC.tags String IOC tags.
ThreatCommand.IOC.status String IOC status is determined based on how recently the IOC was last seen. (Active/Retired).The domain is active for 3 months, the Email address for 2 months, the File hash for 1 year, the IP address for 2 weeks, and the URL for 2 months.
ThreatCommand.IOC.is_known_ioc Boolean Whether the IOC is known (Relevant to enrichment only).
ThreatCommand.IOC.related_malware String Malware related to the IOC (Relevant to enrichment only).
ThreatCommand.IOC.RelatedThreatActors.value String Threat actors related to the IOC (Relevant to enrichment only).
ThreatCommand.IOC.related_campaign String Related campaign (Relevant to enrichment only).
ThreatCommand.IOC.first_seen Date IOC first seen date.
ThreatCommand.IOC.last_seen Date IOC last seen date.
ThreatCommand.IOC.update_seen Date IOC updated seen date (Relevant to enrichment only).
ThreatCommand.IOC.is_whitelisted Boolean Whether the IOC is whitelisted.
ThreatCommand.IOC.Severity.value String IOC severity value.
ThreatCommand.IOC.Severity.score Number IOC severity score.
ThreatCommand.IOC.Severity.origin String IOC severity origin (Relevant to enrichment only).
ThreatCommand.IOC.DnsRecord.value String IOC DNS recorded value (Relevant to enrichment only).
ThreatCommand.IOC.DnsRecord.type String IOC DNS recorded type (Relevant to enrichment only).
ThreatCommand.IOC.DnsRecord.first_resolved Date IOC DNS recorded first resolved (Relevant to enrichment only).
ThreatCommand.IOC.DnsRecord.last_resolved Date IOC DNS recorded last resolved (Relevant to enrichment only).
ThreatCommand.IOC.DnsRecord.count String IOC DNS record count (Relevant to enrichment only).
ThreatCommand.IOC.subdomains String IOC subdomain (Relevant to enrichment only).
ThreatCommand.IOC.History.status String History statuses (Relevant to enrichment only).
ThreatCommand.IOC.History.name_servers String History name servers (Relevant to enrichment only).
ThreatCommand.IOC.Current.status String Current statuses (Relevant to enrichment only).
ThreatCommand.IOC.Current.name_servers String Current name servers (Relevant to enrichment only).
ThreatCommand.IOC.Resolution.resolved_ip_address String Resolved IP address (Relevant to domain IOC) (Relevant to enrichment only).
ThreatCommand.IOC.Resolution.resolved_domain String Resolved domain (Relevant to IP IOC) (Relevant to enrichment only).
ThreatCommand.IOC.Resolution.reporting_sources String Reporting sources (Relevant to enrichment only).
ThreatCommand.IOC.RelatedHash.downloaded String Download hashes (Relevant to enrichment only).
ThreatCommand.IOC.RelatedHash.communicating String Communicating hashes (Relevant to enrichment only).
ThreatCommand.IOC.RelatedHashes.referencing String Referencing hashes (Relevant to enrichment only).
ThreatCommand.IOC.antivirus_scan_date Date Antivirus scan date (Relevant to enrichment only).
ThreatCommand.IOC.file_name String File name (Relevant to enrichment only).
ThreatCommand.IOC.file_type String File type (Relevant to enrichment only).
ThreatCommand.IOC.file_author String File author (Relevant to enrichment only).
ThreatCommand.IOC.file_description String File description (Relevant to enrichment only).
ThreatCommand.IOC.file_size Number File size (the file size is shown in bytes) (Relevant to enrichment only).
ThreatCommand.IOC.antivirus_detection_ratio String Antivirus detection ratio (Relevant to enrichment only).
ThreatCommand.IOC.antivirus_detected_engines String Antivirus-detected engines (Relevant to enrichment only).
ThreatCommand.IOC.AntivirusDetection.name String Detection name (Relevant to enrichment only).
ThreatCommand.IOC.AntivirusDetection.version String Detection version (Relevant to enrichment only).
ThreatCommand.IOC.AntivirusDetection.detected Boolean Whether the IOC is detected (Relevant to enrichment only).
ThreatCommand.IOC.AntivirusDetection.result String Detection result (Relevant to enrichment only).
ThreatCommand.IOC.RelatedHash.type String Hash type (Relevant to enrichment only).
ThreatCommand.IOC.RelatedHash.value String Hash value (Relevant to enrichment only).
ThreatCommand.IOC.ip_range String IOC IP range (Relevant to enrichment only).
ThreatCommand.IOC.last_update_date Date IOC last update date (Relevant to search mode only).
ThreatCommand.IOC.geo_location String Geo location code (Relevant to search mode only).
ThreatCommand.IOC.reportedFeeds.id String IOC reported feed ID (Relevant to search mode only).
ThreatCommand.IOC.reportedFeeds.name String IOC reported feed name (Relevant to search mode only).
ThreatCommand.IOC.reportedFeeds.confidence_level Number IOC reported feed confidence level (Relevant to search mode only).

Command example

!threat-command-ioc-search ioc_value=test.com

Context Example

{
    "ThreatCommand": {
        "IOC": {
            "ReportedFeeds": [
                {
                    "confidence_level": 1,
                    "id": "64538007a44a2f2d6740f6be",
                    "name": "2023test"
                },
                {
                    "confidence_level": 1,
                    "id": "64537fa66a2fbddfeb0835f6",
                    "name": "test2023test"
                },
                {
                    "confidence_level": 1,
                    "id": "64537f2a31c0638f03a0e6d7",
                    "name": "test"
                }
            ],
            "first_seen": "2023-05-04T09:47:22.783Z",
            "is_whitelisted": true,
            "last_seen": "2023-05-04T09:51:03.300Z",
            "last_update_date": "2023-05-04T09:58:10.957Z",
            "related_campaigns": [],
            "related_malware": [],
            "related_threat_actors": [],
            "score": 85,
            "severity": "High",
            "status": "Active",
            "tags": [
                "test"
            ],
            "type": "Domains",
            "value": "test.com"
        }
    }
}

Human Readable Output

IOC “test.com”

Value Type Status Is Whitelisted Score Severity Last Update Date
test.com Domains Active true 85 High 2023-05-04T09:58:10.957Z

threat-command-ioc-tags-add


Adds user tags to IOCs. This enables you to classify IOCs and later search for all IOCs with a specific tag. There is no indication of success or failure for this command. The user has to choose a correct and existing IOC.

Base Command

threat-command-ioc-tags-add

Input

Argument Name Description Required
ioc_value The IOC value. Required
tag_values Comma-separated list of tags to add (Tag can be any word). For example: “Example Tag”,”Regional Alert”. Required

Context Output

There is no context output for this command.

Command example

!threat-command-ioc-tags-add ioc_value=test.com tag_values=test

Human Readable Output

The tags “[‘test’]” successfully added to “test.com” IOC.

threat-command-account-whitelist-update


You can add an IOC to your user whitelist (even if it is already on the system whitelist). If you change your mind, you can then revert that decision to rely again on the system designation using the threat-command-account-whitelist-remove command. When an IOC is whitelisted, it will not be sent to integrated security to block. When an IOC is not whitelisted, it will be sent to integrated security devices to block. There is no indication of success or failure for this command. The user has to choose a correct and existing IOC. At least one IOC is required.

Base Command

threat-command-account-whitelist-update

Input

Argument Name Description Required
is_whitelisted The whitelist status for the IOCs. Add to the user whitelist - The IOCs will not be passed to integrated devices. Do not whitelist - The IOCs will be passed to integrated devices, even if the IOCs are on the system whitelist. . Possible values are: Add to the user whitelist, Do not whitelist. Required
domains Comma-separated list of domain IOC values to apply is_whitelisted to. For example: securitywap.com,test.com. Optional
urls Comma-separated list of URL IOC values to apply is_whitelisted to. For example: “http://securitywap.com/path”. Optional
ips Comma-separated list of IP IOC values to apply is_whitelisted to. For example: 8.8.8.8,1.2.3.4. Optional
hashes Comma-separated list of hash IOC values to apply is_whitelisted to. For example: 8100f3d2668f0f61e6c7ea0dfda59458111238dfeeb9bf47d9fa7543abfb6fb7. Optional
emails Comma-separated list of email IOC values to apply is_whitelisted to. For example: test@test.com. Optional

Context Output

There is no context output for this command.

Command example

!threat-command-account-whitelist-update is_whitelisted="Add to the user whitelist" domains=test.com

Human Readable Output

The status “Add to the user whitelist” successfully updated to “[‘test.com’]” IOCs in the account whitelist.

threat-command-account-whitelist-remove


Reverts IOC values to the system-default whitelist status. The ETP Suite automatically whitelists certain IOCs, such as company assets. You can override this designation or ensure that certain IOCs will not be system whitelisted using the threat-command-account-whitelist-update command. There is no indication of success or failure for this command. The user has to choose a correct and existing IOC. At least one IOC is required.

Base Command

threat-command-account-whitelist-remove

Input

Argument Name Description Required
domains Comma-separated list of domain IOC values to be reverted back to the system whitelist default. For example: securitywap.com,test.com. Optional
urls Comma-separated list of URL IOC values to be reverted back to the system whitelist default. For example: “http://securitywap.com/path”. Optional
ips Comma-separated list of domain IOC values to be reverted back to the system whitelist default. For example: 8.8.8.8,1.2.3.4. Optional
hashes Comma-separated list of domain IOC values to be reverted back to the system whitelist default. For example: 8100f3d2668f0f61e6c7ea0dfda59458111238dfeeb9bf47d9fa7543abfb6fb7. Optional
emails Comma-separated list of domain IOC values to be reverted back to the system whitelist default. For example: test@test.com. Optional

Context Output

There is no context output for this command.

Command example

!threat-command-account-whitelist-remove domains=test.com

Human Readable Output

The IOCs “[‘test.com’]” successfully removed from the account whitelist.

threat-command-ioc-blocklist-add


Adds an IOC to an internal Remediation Blocklist. By sending the blocklist to security devices, you can block the IOCs. At least one IOC is required.

Base Command

threat-command-ioc-blocklist-add

Input

Argument Name Description Required
domains Comma-separated list of domain IOC values to add to the Remediation blocklist. For example: securitywap.com,test.com. Optional
urls Comma-separated list of URL IOC values to add to the Remediation blocklist. For example: “http://securitywap.com/path”. Optional
ips Comma-separated list of IP IOC valuesto add to the Remediation blocklist. For example: 8.8.8.8,1.2.3.4. Optional
hashes Comma-separated list of hash IOC values to add to the Remediation blocklist. For example: 8100f3d2668f0f61e6c7ea0dfda59458111238dfeeb9bf47d9fa7543abfb6fb7. Optional
emails Comma-separated list of email IOC values to add to the Remediation blocklist. For example: test@test.com. Optional

Context Output

There is no context output for this command.

Command example

!threat-command-ioc-blocklist-add domains=test.com

Human Readable Output

The IOCs “[‘test.com’]” successfully added to the remediation blocklist.

threat-command-ioc-blocklist-remove


Removes IOC values from the Remediation blocklist. There is no indication of success or failure for this command. The user has to choose a correct and existing IOC. At least one IOC is required.

Base Command

threat-command-ioc-blocklist-remove

Input

Argument Name Description Required
domains Comma-separated list of domain IOC values to remove from the Remediation blocklist. For example: securitywap.com,test.com. Optional
urls Comma-separated list of URL IOC values to remove from the Remediation blocklist. For example: “http://securitywap.com/path”. Optional
ips Comma-separated list of IP IOC values to remove from the Remediation blocklist. For example: 8.8.8.8,1.2.3.4. Optional
hashes Comma-separated list of hash IOC values to remove from the Remediation blocklist. For example: 8100f3d2668f0f61e6c7ea0dfda59458111238dfeeb9bf47d9fa7543abfb6fb7. Optional
emails Comma-separated list of email IOC values to remove from the Remediation blocklist. For example: test@test.com. Optional

Context Output

There is no context output for this command.

Command example

!threat-command-ioc-blocklist-remove domains=test.com

Human Readable Output

The IOCs “[‘test.com’]” successfully removed from the remediation blocklist.

threat-command-ioc-severity-update


Changes the severity of existing IOCs for the requester account (overrides the system severity). At least one IOC is required.

Base Command

threat-command-ioc-severity-update

Input

Argument Name Description Required
severity The severity of the IOCs. Possible values are: High, Medium, Low. Required
domains Comma-separated list of domain IOC values to update the severity. For example: securitywap.com,test.com. Optional
urls Comma-separated list of URL IOC values to update the severity. For example: “http://securitywap.com/path”. Optional
ips Comma-separated list of IP IOC values to update the severity. For example: 8.8.8.8,1.2.3.4. Optional
hashes Comma-separated list of hash IOC values to update the severity. For example: 8100f3d2668f0f61e6c7ea0dfda59458111238dfeeb9bf47d9fa7543abfb6fb7. Optional
emails Comma-separated list of email IOC values to update the severity. For example: test@test.com. Optional

Context Output

There is no context output for this command.

Command example

!threat-command-ioc-severity-update severity=High domains=test.com

Human Readable Output

The severity “High” successfully updated to “[‘test.com’]” IOCs.

threat-command-ioc-comment-add


Adds comments to IOCs. At least one IOC is required.

Base Command

threat-command-ioc-comment-add

Input

Argument Name Description Required
comment The comment to add. Required
domains Comma-separated list of domain IOC values to add the comment to. For example: securitywap.com,test.com. Optional
urls Comma-separated list of URL IOC values to add the comment to. For example: “http://securitywap.com/path”. Optional
ips Comma-separated list of IP IOC values to add the comment to. For example: 8.8.8.8,1.2.3.4. Optional
hashes Comma-separated list of hash IOC values to add the comment to. For example: 8100f3d2668f0f61e6c7ea0dfda59458111238dfeeb9bf47d9fa7543abfb6fb7. Optional
emails Comma-separated list of email IOC values to add the comment to. For example: test@test.com. Optional

Context Output

There is no context output for this command.

Command example

!threat-command-ioc-comment-add comment=test domains=test.com

Human Readable Output

The comment “test” successfully updated to “[‘test.com’]” IOCs.

threat-command-enrichment-quota-usage


Gets the current API enrichment credits (“quota”) usage for the requester account.

Base Command

threat-command-enrichment-quota-usage

Input

There are no input arguments for this command.

Context Output

There is no context output for this command.

Command example


#### Context Example

```json
{
    "ThreatCommand": {
        "IOCsQuota": {
            "remaining": 43,
            "time_period": "2023-05-04",
            "total": 50
        }
    }
}

Human Readable Output

Current API enrichment credits (quota)

Time Period Total Remaining
2023-05-04 50 43

threat-command-alert-list


Get a list of alerts with all details.

Base Command

threat-command-alert-list

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Optional
page The page number of the results to retrieve (1-based). Default is 1. Optional
page_size The number of objects per page. Optional
limit The maximum number of records to retrieve. Default is 50. Optional
retrieve_ids_only Retrieve alert IDs only. Set to False in order to get the alerts with complete data details, and set to True in order to get a list of alerts. Possible values are: true, false. Optional
last_updated_from Start date to fetch from. For example: 2022-12-25T08:38:06Z. Default is 1970-01-01T00:00:00.000Z. Optional
alert_type Alert’s type. Possible values are: Attack Indication, Data Leakage, Phishing, Brand Security, Exploitable Data, vip. Optional
severity Comma-separated list of alert severities. For example:High,Medium. Possible values are: High, Medium, Low. Optional
source_type Comma-separated list of alert source types. For example:Others,Markets. Possible values are: Application Stores, Black Markets, Hacking Forums, Social Media, Paste Sites, Others. Optional
network_type Comma-separated list of alert network types. For example:Clear Web,Dark Web. Possible values are: Clear Web, Dark Web. Optional
matched_asset_value Comma-separated list of alert matched assets. Optional
last_updated_to End date to fetch to. For example: 2022-12-25T08:38:06Z. Optional
source_date_from Start date to fetch from. For example: 2022-12-25T08:38:06Z. Optional
source_date_to End date to fetch to. For example: 2022-12-25T08:38:06Z. Optional
found_date_from Start date to fetch from. For example: 2022-12-25T08:38:06Z. Optional
found_date_to End date to fetch to. For example: 2022-12-25T08:38:06Z. Optional
assigned Show assigned/unassigned alerts. Possible values are: true, false. Optional
is_flagged Show flagged/unflagged alerts. Possible values are: true, false. Optional
is_closed Show closed/open alerts. Possible values are: true, false. Optional
has_ioc Show alerts with IOC results. Possible values are: true, false. Optional

Context Output

Path Type Description
ThreatCommand.Alert.id String Alert ID.
ThreatCommand.Alert.assets.type Date Asset type.
ThreatCommand.Alert.assets.value String Asset value.
ThreatCommand.Alert.assignees String Assignees list.
ThreatCommand.Alert.type String Alert type list.
ThreatCommand.Alert.sub_type String Alert sub type.
ThreatCommand.Alert.title String Alert title.
ThreatCommand.Alert.description String Alert description.
ThreatCommand.Alert.severity String Alert severity.
ThreatCommand.Alert.images String Alert images list.
ThreatCommand.Alert.source_type String Alert type.
ThreatCommand.Alert.source_url String Alert URL source.
ThreatCommand.Alert.source_email String Alert email source.
ThreatCommand.Alert.source_network_type String Alert network type.
ThreatCommand.Alert.source_date Date Alert date.
ThreatCommand.Alert.Tags.created_by String Alert tag creator.
ThreatCommand.Alert.Tags.name String Alert tag name.
ThreatCommand.Alert.Tags.id String Alert tag ID.
ThreatCommand.Alert.related_iocs String Alert related IOC list.
ThreatCommand.Alert.found_date String Alert found date.
ThreatCommand.Alert.update_date String Alert update date.
ThreatCommand.Alert.takedown_status String Alert remediation status.
ThreatCommand.Alert.is_closed Boolean Whether the alert is closed.
ThreatCommand.Alert.is_flagged Boolean Whether the alert is flagged.
ThreatCommand.Alert.related_threat_ids String Alert-related threat IDs.

Command example

!threat-command-alert-list limit=1

Context Example

{
    "ThreatCommand": {
        "Alert": {
            "Tags": [],
            "assets": [],
            "assignees": [],
            "description": "Asfsdfiption",
            "found_date": "2018-01-01T00:00:00.000Z",
            "id": "641b19b45d60c905560fc484",
            "images": [],
            "is_closed": false,
            "is_flagged": false,
            "related_iocs": [
                "https://test.com/cghostinfo"
            ],
            "related_threat_ids": [],
            "severity": "Low",
            "source_date": "None",
            "source_email": "",
            "source_network_type": "DarkWeb",
            "source_type": "Credit Card Black Market",
            "source_url": "https://test.com/cghostinfo",
            "sub_type": "VulnerabilityInTechnologyInUse",
            "takedown_status": "NotSent",
            "title": "sdfsdf",
            "type": "AttackIndication",
            "update_date": "2018-01-01T00:00:00.000Z"
        }
    }
}

Human Readable Output

Alert list

Id Type Sub Type Title Description Severity Found Date Is Closed
641b19b45d60c905560fc484 AttackIndication VulnerabilityInTechnologyInUse sdfsdf Asfsdfiption Low 2018-01-01T00:00:00.000Z false

threat-command-alert-takedown-request


Send a takedown request for the selected alert (Request that Threat Command will contact the host to request a takedown of a malicious domain, website, or mobile application).

Base Command

threat-command-alert-takedown-request

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required
target Takedown target. Available for phishing scenarios only. If you have evidence of malicious activity associated with this domain, select Domain. Possible values are: Domain, Website. Default is Domain. Optional
close_alert_after_success Whether to close the alert after successful remediation. Possible values are: true, false. Optional

Context Output

There is no context output for this command.

threat-command-alert-takedown-request-status-get


Get the alert’s takedown status.

Base Command

threat-command-alert-takedown-request-status-get

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required

Context Output

Path Type Description
ThreatCommand.Alert.takedown_status String Alert’s takedown status.

Command example

!threat-command-alert-takedown-request-status-get alert_id=1234

Context Example

{
    "ThreatCommand": {
        "Alert": {
            "id": "1234",
            "takedown_status": "\"NotSent\""
        }
    }
}

Human Readable Output

Takedown status for alert “1234”

Takedown Status
“NotSent”

threat-command-alert-create


Create a new alert. You have to insert scenario or type and sub_type.

Base Command

threat-command-alert-create

Input

Argument Name Description Required
found_date Alert’s found date. For example: 2022-12-25T08:38:06Z. The defaut value is the current time. Optional
title Alert’s title. Required
description Alert’s description. Required
type Alert’s type (dependencies - use threat-command-alert-type-list command to get all the alert types). Required while scenario not inserted. Possible values are: Attack Indication, Data Leakage, Phishing, Brand Security, Exploitable Data, vip. Optional
sub_type Alert subtype (dependencies - use threat-command-alert-type-list command to get all the alert subtypes). Required while scenario not inserted. Optional
severity Alert’s severity. Possible values are: High, Medium, Low. Required
source_type Alert source type (dependencies - use threat-command-alert-source-type-list command to get all the alert source types). Required
source_network_type Source network type. Possible values are: Clear Web, Dark Web. Required
source_url The source URL of the alert. . Optional
source_date Alert’s source date. For example: 2022-12-25T08:38:06Z. Optional
image_entry_ids Comma-separated list of image entry IDs to attach to the alert. Allowed image types: gif,jpeg. Optional
scenario If provided, the related values will override any type and sub_type parameters (dependencies - use the threat-command-alert-scenario-list command to get all the alert scenarios). Optional

Context Output

Path Type Description
ThreatCommand.Alert.id String Alert ID.

Command example

!threat-command-alert-create title="test" description="test" severity="Low" source_type="Application Store" source_network_type="Clear Web" source_url="test.com" scenario="ACompanyEmailAddressReportedAsMalicious"

Context Example

{
    "ThreatCommand": {
        "Alert": {
            "id": "64538b71ba5d3f7a8fb27ddc"
        }
    }
}

Human Readable Output

Alert successfully created

Id
64538b71ba5d3f7a8fb27ddc

threat-command-alert-close


Close alert.

Base Command

threat-command-alert-close

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required
reason Alert’s closed reason. Possible values are: Problem Solved, Informational Only, Problem We Are Already Aware Of, Company Owned Domain, Legitimate Application/Profile, Not Related To My Company, False Positive, Other. Required
comment Alert’s comments. Optional
is_hidden Alerts’ hidden status (Delete alert from the account instance only when reason is FalsePositive). Possible values are: true, false. Optional
rate Alert’s rate. Rate range: 0-5 (The range not officaly documented). Possible values are: 0, 1, 2, 3, 4, 5. Optional

Context Output

Path Type Description
ThreatCommand.Alert.id String Alert ID.
ThreatCommand.Alert.is_closed String Whether the alert is closed.

Command example

!threat-command-alert-close alert_id=1234 reason=Other

Context Example

{
    "ThreatCommand": {
        "Alert": {
            "id": "1234",
            "is_closed": true
        }
    }
}

Human Readable Output

Alert “1234” successfully closed

Id Is Closed
1234 true

threat-command-alert-severity-update


Change the alert’s severity. Changing the severity level of alerts can help to prioritize alert management.

Base Command

threat-command-alert-severity-update

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required
severity The desired severity. Possible values are: High, Medium, Low. Required

Context Output

Path Type Description
ThreatCommand.Alert.id String Alert ID.
ThreatCommand.Alert.severity String Alert severity.

Command example

!threat-command-alert-severity-update alert_id=1234 severity=Medium

Context Example

{
    "ThreatCommand": {
        "Alert": {
            "id": "1234",
            "severity": "Medium"
        }
    }
}

Human Readable Output

Alert “1234” severity successfully updated to “Medium”

Id Severity
1234 Medium

threat-command-alert-blocklist-get


Get alert’s blocklist status.

Base Command

threat-command-alert-blocklist-get

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required

Context Output

Path Type Description
ThreatCommand.Alert.id String Alert ID.
ThreatCommand.Alert.BlockList.value String Alert blocklist value.
ThreatCommand.Alert.BlockList.status String Alert blocklist status.

Command example

!threat-command-alert-blocklist-get alert_id=1234

Context Example

{
    "ThreatCommand": {
        "Alert": {
            "BlockList": [],
            "id": "1234"
        }
    }
}

Human Readable Output

Blocklist for alert “1234”

No entries.

threat-command-alert-blocklist-update


Change selected IOCs blocklist status.

Base Command

threat-command-alert-blocklist-update

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required
domains Comma-separated list of domain IOC values to add. For example: securitywap.com,test.com. Optional
urls Comma-separated list of URL IOC values to add. For example: “http://securitywap.com/path”. Optional
ips Comma-separated list of IP IOC values to add. For example: 8.8.8.8,1.2.3.4. Optional
emails Comma-separated list of email IOC values to add. For example: test@test.com. Optional
blocklist_status Blocklist status. Possible values are: Sent, Not Sent. Required

Context Output

There is no context output for this command.

threat-command-alert-ioc-report


Report IOCs to external sources (Report the URLs and domains that are included in an alert to external sources. This can warn others of the potential danger of those IOCs).

Base Command

threat-command-alert-ioc-report

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required
external_sources Comma-separated list of the desired source names (dependencies - use threat-command-source-ioc-get to get all the source names). For example:GoogleWebRisk,PhishTank.Since there are variety of sources that accept different types of IOCs, select only sources that accept the alert IOCs. Required

Context Output

There is no context output for this command.

threat-command-alert-assign


Assign an alert to other ETP Suite users. When an alert is assigned, the assignee will receive a notification. Mainly used to assign alerts.

Base Command

threat-command-alert-assign

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required
user_id Assigned user ID (dependencies - use threat-command-mssp-user-list or threat-command-account-user-list to get user IDs). Required
is_mssp If the assigned user is an MSSP user or not. Possible values are: true, false. Optional

Context Output

Path Type Description
ThreatCommand.Alert.id String Alert ID.
ThreatCommand.Alert.assignees String Assignees list.

Command example

!threat-command-alert-assign alert_id=1234 user_id=1234

Context Example

{
    "ThreatCommand": {
        "Alert": {
            "assignees": [
                "1234"
            ],
            "id": "1234"
        }
    }
}

Human Readable Output

Alert “1234” successfully assign to user “631ef479b675f72ec9309785”

Id Assignees
1234 1234

threat-command-alert-unassign


Unassign an alert from all users.

Base Command

threat-command-alert-unassign

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required

Context Output

Path Type Description
ThreatCommand.Alert.id String Alert ID.
ThreatCommand.Alert.assignees String Assignees list.

Command example

!threat-command-alert-unassign alert_id=1234

Context Example

{
    "ThreatCommand": {
        "Alert": {
            "assignees": null,
            "id": "1234"
        }
    }
}

Human Readable Output

Alert ‘1234’ successfully unassigned from any user

Id
1234

threat-command-alert-reopen


Reopen alert.

Base Command

threat-command-alert-reopen

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required

Context Output

There is no context output for this command.

Command example

!threat-command-alert-reopen alert_id=1234

Human Readable Output

Alert “1234” successfully re-opened.

threat-command-alert-tag-add


Adds a tag to an alert. This enables you to classify alerts and later search for all alerts with a specific tag.

Base Command

threat-command-alert-tag-add

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required
tag_name The new tag string. Required

Context Output

There is no context output for this command.

Command example

!threat-command-alert-tag-add alert_id=1234 tag_name=test

Human Readable Output

The tag “test” successfully added to “1234” Alert.

threat-command-alert-tag-remove


Removes a tag from the alert.

Base Command

threat-command-alert-tag-remove

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required
tag_id Tag’s unique ID to remove (dependencies - use threat-command-alert-list command to get all the tag IDs). Required

Context Output

There is no context output for this command.

Command example

!threat-command-alert-tag-remove alert_id=6432e3aa6ff61aae819dc46b tag_id=1234

Human Readable Output

The tag “6453871c0d771fdc938f18d5” successfully removed from “6432e3aa6ff61aae819dc46b” Alert.

threat-command-alert-send-mail


Send mail with the alert details and a question.

Base Command

threat-command-alert-send-mail

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required
email_addresses Comma-separated list of destinaions email addresses. Required
content Content added to the alert details. Required

Context Output

There is no context output for this command.

Command example

!threat-command-alert-send-mail alert_id=6432e3aa6ff61aae819dc46b email_addresses=test@test.com content=test

Human Readable Output

The alert “6432e3aa6ff61aae819dc46b” successfully send to “[‘test@test.com’]”.

threat-command-alert-analyst-ask


Send a question to an analyst about the requested alert. Questions can revolve around an alert explanation, a request for more context, recommended remediation steps, or requests for threat actor engagement. In order to get the conversation with the analyst, use the threat-command-alert-analyst-conversation-list command.

Base Command

threat-command-alert-analyst-ask

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required
question Question added to the alert details. Required

Context Output

There is no context output for this command.

Command example

!threat-command-alert-analyst-ask alert_id=1234 question=test

Human Readable Output

The alert “1234” successfully sent to the analyst.

threat-command-alert-analyst-conversation-list


Get alert’s analyst response

Base Command

threat-command-alert-analyst-conversation-list

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required

Context Output

Path Type Description
ThreatCommand.Alert.id String Alert ID.
ThreatCommand.Alert.Message.date String Response date.
ThreatCommand.Alert.Message.initiator String Response initiator.
ThreatCommand.Alert.Message.message String Response message.

Command example

!threat-command-alert-analyst-conversation-list alert_id=1234

Context Example

{
    "ThreatCommand": {
        "Alert": {
            "Message": [
                {
                    "date": "2023-04-03T15:02:34.641Z",
                    "initiator": "test@test.com",
                    "message": "Hello"
                },
                {
                    "date": "2023-04-03T15:40:56.195Z",
                    "initiator": "Intsights",
                    "message": "Hi"
                },
                {
                    "date": "2023-04-03T18:29:41.169Z",
                    "initiator": "test@test.com",
                    "message": "thank you"
                },
            ],
            "id": "1234"
        }
    }
}

Human Readable Output

Alert conversation with analyst

Initiator Message Date
test@test.com Hello 2023-04-03T15:02:34.641Z
Intsights Hi 2023-04-03T15:40:56.195Z
test@test.com thank you 2023-04-03T18:29:41.169Z

threat-command-alert-activity-log-get


Get alert activity log.

Base Command

threat-command-alert-activity-log-get

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required

Context Output

Path Type Description
ThreatCommand.Alert.ActivityLog.rate Number Alert rate.
ThreatCommand.Alert.ActivityLog.type String Alert type.
ThreatCommand.Alert.ActivityLog.sub_types String Alert subtypes.
ThreatCommand.Alert.ActivityLog.initiator String Alert initiator.
ThreatCommand.Alert.ActivityLog.created_date Date Alert created date.
ThreatCommand.Alert.ActivityLog.update_date Date Alert update date.
ThreatCommand.Alert.ActivityLog.read_by String Alert read by.
ThreatCommand.Alert.ActivityLog.id String Alert created ID.
ThreatCommand.Alert.ActivityLog.tag_names String Alert tag names.
ThreatCommand.Alert.ActivityLog.tag_ids String Alert tag IDs.
ThreatCommand.Alert.ActivityLog.Mail.note_id String Alert note ID.
ThreatCommand.Alert.ActivityLog.Mail.question String Alert mail question.
ThreatCommand.Alert.ActivityLog.Mail.Replies.email String Alert mail reply email.
ThreatCommand.Alert.ActivityLog.Mail.Replies.token String Alert mail reply token.
ThreatCommand.Alert.ActivityLog.Mail.Replies.date Date Alert mail reply date.
ThreatCommand.Alert.ActivityLog.Mail.Replies.read_by String Alert mail read by.
ThreatCommand.Alert.ActivityLog.Mail.Replies.is_token_valid Boolean Alert mail reply is token valid.
ThreatCommand.Alert.ActivityLog.Messages.initiator_id String Alert message ID.
ThreatCommand.Alert.ActivityLog.Messages.initiator_is_support Boolean Whether asking the analyst is supported.
ThreatCommand.Alert.ActivityLog.Messages.date Date Alert message date.
ThreatCommand.Alert.ActivityLog.Messages.content String Alert message content.

Command example

!threat-command-alert-activity-log-get alert_id=1234

Context Example

{
    "ThreatCommand": {
        "Alert": {
            "ActivityLog": [
                {
                    "created_date": "2023-03-23T20:54:11.730Z",
                    "id": "641cbc73bade6cc1ed3a1a25",
                    "initiator": "59490cd818a3b902664b4ed7",
                    "rate": 0,
                    "read_by": [
                        "631ef479b675f72ec9309785",
                        "64214c014c75609d09ebb767",
                        "64214bc94c75609d09ebb56a",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "sub_types": [
                        "PolicyClose",
                        "PolicyTag"
                    ],
                    "type": "PolicyRule",
                    "update_date": "2023-03-23T20:54:11.730Z"
                },
                {
                    "created_date": "2023-03-26T14:21:10.178Z",
                    "id": "642054d68d62709fc5a6ae9b",
                    "initiator": "631ef479b675f72ec9309785",
                    "rate": 0,
                    "read_by": [
                        "631ef479b675f72ec9309785",
                        "64214c014c75609d09ebb767",
                        "64214bc94c75609d09ebb56a",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "type": "AlertRead",
                    "update_date": "2023-03-26T14:21:10.178Z"
                },
                {
                    "created_date": "2023-03-27T07:13:31.321Z",
                    "id": "6421421b21f4e115ecc8c931",
                    "initiator": "631ef479b675f72ec9309785",
                    "read_by": [
                        "631ef479b675f72ec9309785",
                        "64214c014c75609d09ebb767",
                        "64214bc94c75609d09ebb56a",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "type": "AlertReopened",
                    "update_date": "2023-03-27T07:13:31.321Z"
                },
                {
                    "created_date": "2023-03-27T08:00:49.244Z",
                    "id": "64214d318d62709fc5a99219",
                    "initiator": "64214c014c75609d09ebb767",
                    "rate": 0,
                    "read_by": [
                        "64214c014c75609d09ebb767",
                        "631ef479b675f72ec9309785",
                        "64214bc94c75609d09ebb56a",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "type": "AlertRead",
                    "update_date": "2023-03-27T08:00:49.244Z"
                },
                {
                    "created_date": "2023-03-27T13:20:02.865Z",
                    "id": "6421980221f4e115ecca9660",
                    "initiator": "631ef479b675f72ec9309785",
                    "rate": 0,
                    "read_by": [
                        "631ef479b675f72ec9309785",
                        "64214bc94c75609d09ebb56a",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "tag_ids": [
                        "641cbc74bade6cc1ed3a1a2a"
                    ],
                    "tag_names": [
                        "Historical Alert"
                    ],
                    "type": "RemoveTag",
                    "update_date": "2023-03-27T13:20:02.865Z"
                },
                {
                    "created_date": "2023-03-28T11:04:59.497Z",
                    "id": "6422c9db1b2080e62a5f60a0",
                    "initiator": "64214bc94c75609d09ebb56a",
                    "rate": 0,
                    "read_by": [
                        "64214bc94c75609d09ebb56a",
                        "631ef479b675f72ec9309785",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "type": "AlertRead",
                    "update_date": "2023-03-28T11:04:59.497Z"
                },
                {
                    "created_date": "2023-03-28T11:05:02.300Z",
                    "id": "6422c9de071e6ceab7106a04",
                    "initiator": "64214bc94c75609d09ebb56a",
                    "rate": 0,
                    "read_by": [
                        "64214bc94c75609d09ebb56a",
                        "631ef479b675f72ec9309785",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "tag_ids": [
                        "6422c9de071e6ceab7106a05"
                    ],
                    "tag_names": [
                        "test2"
                    ],
                    "type": "AddTag",
                    "update_date": "2023-03-28T11:05:02.300Z"
                },
                {
                    "created_date": "2023-03-28T11:47:43.170Z",
                    "id": "6422d3df28c6b34a7004b43d",
                    "initiator": "631ef479b675f72ec9309785",
                    "rate": 0,
                    "read_by": [
                        "631ef479b675f72ec9309785",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "tag_ids": [
                        "6422d3df28c6b34a7004b43e"
                    ],
                    "tag_names": [
                        "123"
                    ],
                    "type": "AddTag",
                    "update_date": "2023-03-28T11:47:43.170Z"
                },
                {
                    "created_date": "2023-03-30T16:53:26.193Z",
                    "id": "6425be860112b8035eedef2b",
                    "initiator": "631ef479b675f72ec9309785",
                    "rate": 0,
                    "read_by": [
                        "631ef479b675f72ec9309785",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "type": "ChangedSeverity",
                    "update_date": "2023-03-30T16:53:26.193Z"
                },
                {
                    "created_date": "2023-04-03T14:10:35.277Z",
                    "id": "642ade5b841e1c963048d9fe",
                    "initiator": "631ef479b675f72ec9309785",
                    "rate": 0,
                    "read_by": [
                        "631ef479b675f72ec9309785",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "type": "Assign",
                    "update_date": "2023-04-03T14:10:35.277Z"
                },
                {
                    "created_date": "2023-04-03T14:11:46.331Z",
                    "id": "642adea264ed2f6ce85abf13",
                    "initiator": "631ef479b675f72ec9309785",
                    "rate": 0,
                    "read_by": [
                        "631ef479b675f72ec9309785",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "type": "Assign",
                    "update_date": "2023-04-03T14:11:46.331Z"
                },
                {
                    "created_date": "2023-04-03T14:11:50.358Z",
                    "id": "642adea664ed2f6ce85abf8c",
                    "initiator": "631ef479b675f72ec9309785",
                    "rate": 0,
                    "read_by": [
                        "631ef479b675f72ec9309785",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "type": "Assign",
                    "update_date": "2023-04-03T14:11:50.358Z"
                },
                {
                    "created_date": "2023-04-03T14:11:55.831Z",
                    "id": "642adeab841e1c963048dba1",
                    "initiator": "631ef479b675f72ec9309785",
                    "rate": 0,
                    "read_by": [
                        "631ef479b675f72ec9309785",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "type": "Assign",
                    "update_date": "2023-04-03T14:11:55.831Z"
                },
                {
                    "Messages": [
                        {
                            "content": "Hello",
                            "date": "2023-04-03T15:02:34.793Z",
                            "initiator_id": "631ef479b675f72ec9309785",
                            "initiator_is_support": false
                        },
                        {
                            "content": "Hi",
                            "date": "2023-04-03T15:40:56.197Z",
                            "initiator_is_support": true
                        },
                    ],
                    "created_date": "2023-04-03T15:02:34.793Z",
                    "id": "642aea8ababb12ffd004d60e",
                    "initiator": "631ef479b675f72ec9309785",
                    "rate": 0,
                    "read_by": [
                        "631ef479b675f72ec9309785",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "type": "AskTheAnalystRequest",
                    "update_date": "2023-05-04T10:11:58.270Z"
                },
                {
                    "created_date": "2023-04-03T15:02:34.795Z",
                    "id": "642aea8ababb12ffd004d610",
                    "initiator": "631ef479b675f72ec9309785",
                    "rate": 0,
                    "read_by": [
                        "631ef479b675f72ec9309785",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "type": "AskTheAnalystQuestion",
                    "update_date": "2023-04-03T15:02:34.795Z"
                },
                {
                    "created_date": "2023-04-03T15:40:56.199Z",
                    "id": "642af388ffcc326df6ba58da",
                    "initiator": "System",
                    "rate": 0,
                    "read_by": [
                        "63a1cc800d782c827d29e73d",
                        "631ef479b675f72ec9309785"
                    ],
                    "type": "AskTheAnalystAnswer",
                    "update_date": "2023-04-03T15:40:56.199Z"
                },
                {
                    "created_date": "2023-04-03T18:29:41.326Z",
                    "id": "642b1b1549600a740c70b1c7",
                    "initiator": "631ef479b675f72ec9309785",
                    "rate": 0,
                    "read_by": [
                        "631ef479b675f72ec9309785",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "type": "AskTheAnalystQuestion",
                    "update_date": "2023-04-03T18:29:41.326Z"
                },
                {
                    "created_date": "2023-04-03T19:06:43.557Z",
                    "id": "642b23c3128075fc8c55ad23",
                    "initiator": "System",
                    "rate": 0,
                    "read_by": [
                        "631ef479b675f72ec9309785",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "type": "AskTheAnalystAnswer",
                    "update_date": "2023-04-03T19:06:43.557Z"
                },
                {
                    "created_date": "2023-04-04T10:30:26.005Z",
                    "id": "642bfc42841e1c96304dd178",
                    "initiator": "631ef479b675f72ec9309785",
                    "rate": 0,
                    "read_by": [
                        "631ef479b675f72ec9309785",
                        "63a1cc800d782c827d29e73d"
                    ],
                    "type": "AskTheAnalystQuestion",
                    "update_date": "2023-04-04T10:30:26.005Z"
                },
                {
                    "created_date": "2023-04-04T13:59:48.026Z",
                    "id": "642c2d54128075fc8c564fdb",
                    "initiator": "System",
                    "rate": 0,
                    "read_by": [
                        "631ef479b675f72ec9309785"
                    ],
                    "type": "AskTheAnalystAnswer",
                    "update_date": "2023-04-04T13:59:48.026Z"
                },
                {
                    "created_date": "2023-05-04T10:10:24.478Z",
                    "id": "645384909b3179c05ca2ad41",
                    "initiator": "API",
                    "type": "AlertClosed",
                    "update_date": "2023-05-04T10:10:24.478Z"
                },
                {
                    "created_date": "2023-05-04T10:10:33.304Z",
                    "id": "645384999b3179c05ca2adf6",
                    "initiator": "API",
                    "rate": 0,
                    "type": "ChangedSeverity",
                    "update_date": "2023-05-04T10:10:33.304Z"
                },
                {
                    "created_date": "2023-05-04T10:11:07.781Z",
                    "id": "645384bbd3e54df9a593372b",
                    "initiator": "API",
                    "rate": 0,
                    "type": "Assign",
                    "update_date": "2023-05-04T10:11:07.781Z"
                },
                {
                    "created_date": "2023-05-04T10:11:16.487Z",
                    "id": "645384c4d3e54df9a59338b4",
                    "initiator": "API",
                    "rate": 0,
                    "type": "Unassign",
                    "update_date": "2023-05-04T10:11:16.487Z"
                },
                {
                    "created_date": "2023-05-04T10:11:25.161Z",
                    "id": "645384cd08e4bc1e2948ec09",
                    "initiator": "API",
                    "type": "AlertReopened",
                    "update_date": "2023-05-04T10:11:25.161Z"
                },
                {
                    "created_date": "2023-05-04T10:11:33.638Z",
                    "id": "645384d511ba24a35d0ab861",
                    "initiator": "API",
                    "rate": 0,
                    "tag_ids": [
                        "645384d511ba24a35d0ab862"
                    ],
                    "tag_names": [
                        "test"
                    ],
                    "type": "AddTag",
                    "update_date": "2023-05-04T10:11:33.638Z"
                },
                {
                    "created_date": "2023-05-04T10:11:58.271Z",
                    "id": "645384ee6a6f7be836b95c00",
                    "initiator": "API",
                    "rate": 0,
                    "type": "AskTheAnalystQuestion",
                    "update_date": "2023-05-04T10:11:58.271Z"
                }
            ],
            "id": "1234"
        }
    }
}

Human Readable Output

Alert “1234” activity log

Id Type Update Date Sub Types Initiator
641cbc73bade6cc1ed3a1a25 PolicyRule 2023-03-23T20:54:11.730Z PolicyClose,
PolicyTag
59490cd818a3b902664b4ed7
642054d68d62709fc5a6ae9b AlertRead 2023-03-26T14:21:10.178Z   631ef479b675f72ec9309785
6421421b21f4e115ecc8c931 AlertReopened 2023-03-27T07:13:31.321Z   631ef479b675f72ec9309785
64214d318d62709fc5a99219 AlertRead 2023-03-27T08:00:49.244Z   64214c014c75609d09ebb767
6421980221f4e115ecca9660 RemoveTag 2023-03-27T13:20:02.865Z   631ef479b675f72ec9309785
6422c9db1b2080e62a5f60a0 AlertRead 2023-03-28T11:04:59.497Z   64214bc94c75609d09ebb56a
6422c9de071e6ceab7106a04 AddTag 2023-03-28T11:05:02.300Z   64214bc94c75609d09ebb56a
6422d3df28c6b34a7004b43d AddTag 2023-03-28T11:47:43.170Z   631ef479b675f72ec9309785
6425be860112b8035eedef2b ChangedSeverity 2023-03-30T16:53:26.193Z   631ef479b675f72ec9309785
642ade5b841e1c963048d9fe Assign 2023-04-03T14:10:35.277Z   631ef479b675f72ec9309785
642adea264ed2f6ce85abf13 Assign 2023-04-03T14:11:46.331Z   631ef479b675f72ec9309785
642adea664ed2f6ce85abf8c Assign 2023-04-03T14:11:50.358Z   631ef479b675f72ec9309785
642adeab841e1c963048dba1 Assign 2023-04-03T14:11:55.831Z   631ef479b675f72ec9309785
642aea8ababb12ffd004d60e AskTheAnalystRequest 2023-05-04T10:11:58.270Z   631ef479b675f72ec9309785
642aea8ababb12ffd004d610 AskTheAnalystQuestion 2023-04-03T15:02:34.795Z   631ef479b675f72ec9309785
642af388ffcc326df6ba58da AskTheAnalystAnswer 2023-04-03T15:40:56.199Z   System
642b1b1549600a740c70b1c7 AskTheAnalystQuestion 2023-04-03T18:29:41.326Z   631ef479b675f72ec9309785
642b23c3128075fc8c55ad23 AskTheAnalystAnswer 2023-04-03T19:06:43.557Z   System
642bfc42841e1c96304dd178 AskTheAnalystQuestion 2023-04-04T10:30:26.005Z   631ef479b675f72ec9309785
642c2d54128075fc8c564fdb AskTheAnalystAnswer 2023-04-04T13:59:48.026Z   System
645384909b3179c05ca2ad41 AlertClosed 2023-05-04T10:10:24.478Z   API
645384999b3179c05ca2adf6 ChangedSeverity 2023-05-04T10:10:33.304Z   API
645384bbd3e54df9a593372b Assign 2023-05-04T10:11:07.781Z   API
645384c4d3e54df9a59338b4 Unassign 2023-05-04T10:11:16.487Z   API
645384cd08e4bc1e2948ec09 AlertReopened 2023-05-04T10:11:25.161Z   API
645384d511ba24a35d0ab861 AddTag 2023-05-04T10:11:33.638Z   API
645384ee6a6f7be836b95c00 AskTheAnalystQuestion 2023-05-04T10:11:58.271Z   API

threat-command-alert-csv-get


Get alert’s CSV file in case of credentials leakage or leaked credit cards alerts.

Base Command

threat-command-alert-csv-get

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required

Context Output

Path Type Description
ThreatCommand.CSV.alert_id String Alert ID.
ThreatCommand.CSV.content Unknown Content of CSV file.
InfoFile.EntryID string The EntryID of the CSV file.
InfoFile.Extension string The extension of the CSV file.
InfoFile.Name string The name of the CSV file.
InfoFile.Info string The info of the CSV file.
InfoFile.Size number The size of the CSV file.
InfoFile.Type string The type of the CSV file.

Command example

!threat-command-alert-csv-get alert_id=1234

Context Example

{
    "ThreatCommand": {
      "CSV": {
        "alert_id": "1234",
        "content": [
          {
            "email": "someone@my.com",
            "password": "password",
            "raw_line": "someone@my.com|password"
          }
        ]
      }
    },
    "InfoFile": {
        "EntryID": "35323@b5fa0da4-31d6-4517-8d5c-484d4bb598ac",
        "Extension": "csv",
        "Info": "text/csv; charset=utf-8",
        "Name": "1234.csv",
        "Size": 150,
        "Type": "ASCII text, with CRLF line terminators"
    }
}

Human Readable Output

Alert “1234” CSV file.

threat-command-alert-note-add


Add a note to the alert. You can add notes, as text or uploaded files, to an alert that can be seen by internal users. Each note is accompanied by the name of the note creator. Other users can reply to notes. Alert notes remain with the alert, even after it is closed or otherwise remediated.

Base Command

threat-command-alert-note-add

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required
note Desired note. Required
entry_ids Comma-separated list of file entry IDs. Allowed types: pdf,csv,doc,docx,png,txt,jpeg,jpg. Optional

Context Output

There is no context output for this command.

Command example

!threat-command-alert-note-add alert_id=1234 note=test

Human Readable Output

Note successfully add to alert “1234”.

threat-command-alert-image-list


List alert images by ID.

Base Command

threat-command-alert-image-list

Input

Argument Name Description Required
alert_id Alert’s unique ID (dependencies - use threat-command-alert-list command to get all the alert IDs). Required

Context Output

There is no context output for this command.

Command example

!threat-command-alert-image-list alert_id=1234

Human Readable Output

Alert “1234” does not contain images.

threat-command-cve-list


Get CVE’s list from account.

Base Command

threat-command-cve-list

Input

Argument Name Description Required
limit The maximum number of records to retrieve. Default is 50. Optional
offset This field is used for pagination. Each request is limited to 1000 results. To get the next page, send the returned “nextOffset” parameter back to the sever as “offset”. Optional
publish_date_from CVE’s publish date minimum value. For example: 2022-12-25T08:38:06Z. Optional
publish_date_to CVE’s publish date maximum value. For example: 2022-12-25T08:38:06Z. Optional
update_date_from CVE’s update date minimum value. For example: 2022-12-25T08:38:06Z. Optional
update_date_to CVE’s update date maximum value. For example: 2022-12-25T08:38:06Z. Optional
severity_list Comma-separated list of CVE severities. Possible values are: Critical, High, Medium, Low. Optional
cpe_list Comma-separated list of CPEs. Optional
cve_ids Comma-separated list of specific CVE IDs. Optional

Context Output

Path Type Description
ThreatCommand.CVE.id String CVE ID.
ThreatCommand.CVE.Cpe.value String CVE CPE value.
ThreatCommand.CVE.Cpe.title String CVE CPE title.
ThreatCommand.CVE.Cpe.vendor_product String CVE CPE vendor.
ThreatCommand.CVE.published_date Date CVE CP publish date.
ThreatCommand.CVE.update_date Date CVE update date.
ThreatCommand.CVE.severity String CVE severity.
ThreatCommand.CVE.intsights_score Number CVE insight score.
ThreatCommand.CVE.cvss_score Number CVE CVSS score.
ThreatCommand.CVE.mentions_amount Number CVE mentions amount.
ThreatCommand.CVE.paste_site_mentions Number CVE paste site mentions.
ThreatCommand.CVE.hacking_forum_mentions Number CVE hacking forum mentions.
ThreatCommand.CVE.instant_message_mentions Number CVE instant message mentions.
ThreatCommand.CVE.dark_web_mentions Number CVE dark web mentions.
ThreatCommand.CVE.clear_web_cyber_blogs_mentions Number CVE clear web cyber blogs mentions.
ThreatCommand.CVE.code_repositories_mentions Number CVE code repositories mentions.
ThreatCommand.CVE.exploit_mentions Number CVE exploit mentions.
ThreatCommand.CVE.social_media_mentions Number CVE social media mentions.
ThreatCommand.CVE.first_mention_date Date CVE first mention date.
ThreatCommand.CVE.last_mention_date Date CVE last mention date.
ThreatCommand.CVE.exploit_availability Boolean CVE exploit availability.
ThreatCommand.CVE.vulnerability_origin String CVE last vulnerability origin.
ThreatCommand.CVE.related_threat_actors String Related threat actors.
ThreatCommand.CVE.related_malware String Related malware.
ThreatCommand.CVE.related_campaigns String Related campaigns.

Command example

!threat-command-cve-list limit=1

Context Example

{
    "ThreatCommand": {
        "CVE": {
            "clear_web_cyber_blogs_mentions": 1,
            "code_repositories_mentions": 0,
            "cpe": [
                {
                    "title": "Familyconnect Project 1.5.0 Android",
                    "value": "cpe:2.3:a:familyconnect_project:familyconnect:1.5.0:*:*:*:*:android:*:*",
                    "vendor_product": "Familyconnect Project Familyconnect"
                }
            ],
            "cvss_score": 5.4,
            "dark_web_mentions": 0,
            "exploit_availability": false,
            "exploit_mentions": 0,
            "first_mention_date": "2021-11-03T19:39:00.000Z",
            "hacking_forum_mentions": 0,
            "id": "CVE-2014-5600",
            "instant_message_mentions": 0,
            "intsights_score": 17,
            "last_mention_date": "2021-11-03T19:39:00.000Z",
            "paste_site_mentions": 1,
            "poc_mentions": 0,
            "published_date": "2014-09-09T01:55:00.000Z",
            "related_campaigns": [],
            "related_malware": [],
            "related_threat_actors": [],
            "severity": "Low",
            "social_media_mentions": 0,
            "update_date": "2023-04-30T22:00:37.673Z",
            "vulnerability_origin": [
                "Technologies in use asset"
            ]
        }
    }
}

Human Readable Output

CVE list

Id Published Date Update Date Severity Intsights Score Cvss Score
CVE-2014-5600 2014-09-09T01:55:00.000Z 2023-04-30T22:00:37.673Z Low 17 5.4

threat-command-cve-add


Add CVEs to account.

Base Command

threat-command-cve-add

Input

Argument Name Description Required
cve_ids Comma-separated list of CVEs unique IDs. Required

Context Output

There is no context output for this command.

Command example

!threat-command-cve-add cve_ids=CVE-1999-0002

Human Readable Output

The “CVE-1999-0002” CVEs successfully added.

threat-command-cve-delete


Delete CVEs from account.

Base Command

threat-command-cve-delete

Input

Argument Name Description Required
cve_ids Comma-separated list of CVEs unique IDs (dependencies - use threat-command-cve-listto get all the CVE IDs). Required

Context Output

There is no context output for this command.

Command example

!threat-command-cve-delete cve_ids=CVE-1999-0002

Human Readable Output

The “CVE-1999-0002” CVEs successfully deleted.

threat-command-asset-add


Add assets by type and value. Assets include any company resource that could lead to a potential security threat.

Base Command

threat-command-asset-add

Input

Argument Name Description Required
asset_type The type of asset to add value. For example: asset_type=”Domains” asset_value=”example.com”. (You can get the asset types with threat-command-asset-type-list command). Required
asset_value Asset value. Required

Context Output

Path Type Description
ThreatCommand.Asset.type String The type of the asset.
ThreatCommand.Asset.value String The value of the asset type.

Command example

!threat-command-asset-add asset_type=CompanyNames asset_value=test

Context Example

{
    "ThreatCommand": {
        "Asset": {
            "type": "CompanyNames",
            "value": "test"
        }
    }
}

Human Readable Output

Asset “test” successfully added to “CompanyNames” asset list

Type Value
CompanyNames test

threat-command-asset-list


Get account assets grouped by asset type.

Base Command

threat-command-asset-list

Input

Argument Name Description Required
limit The maximum number of records to retrieve. Default is 50. Optional
all_results Show all results if True. Possible values are: true, false. Optional
asset_types Comma-separated list of alert source types (dependencies - use threat-command-asset-type-list command to get all the asset types). For example:Domains,CompanyNames. . Optional

Context Output

Path Type Description
ThreatCommand.Asset.type String The type of the asset.
ThreatCommand.Asset.value String The value of the asset type.

Command example

!threat-command-asset-list limit=4

Context Example

{
    "ThreatCommand": {
        "Asset": [
            {
                "type": "Domains",
                "value": "com.com"
            },
            {
                "type": "Domains",
                "value": "google.com"
            },
            {
                "type": "Domains",
                "value": "moh.gov.il"
            },
            {
                "type": "Domains",
                "value": "qmasters.co"
            }
        ]
    }
}

Human Readable Output

Asset list

Type Value
Domains com.com
Domains google.com
Domains moh.gov.il
Domains qmasters.co

threat-command-asset-type-list


Get all asset types. Mainly used to add or delete assets.

Base Command

threat-command-asset-type-list

Input

Argument Name Description Required
limit The maximum number of records to retrieve. Default is 50. Optional
all_results Show all results if True. Possible values are: true, false. Optional

Context Output

Path Type Description
ThreatCommand.AssetType String Asset type.

threat-command-asset-delete


Delete asset by type and value.

Base Command

threat-command-asset-delete

Input

Argument Name Description Required
asset_type The type of asset to add value. For example: asset_type=”Domains” asset_value=”example.com”. (You can get the asset types with threat-command-asset-type-list command). Required
asset_value Asset value. Required

Context Output

There is no context output for this command.

Command example

!threat-command-asset-delete asset_type=CompanyNames asset_value=test

Human Readable Output

Asset “test” successfully deleted from “CompanyNames” asset list.

threat-command-account-system-modules-list


List the system modules of your account.

Base Command

threat-command-account-system-modules-list

Input

There are no input arguments for this command.

Context Output

Path Type Description
ThreatCommand.SystemModule.module_name String Module name.
ThreatCommand.SystemModule.status String Whether the module module is enabled.

Command example

Human Readable Output

System modules

Module Name Status
discovery true
remediation true
ioc true
virtualappliance true
investigationpage true
threatlibrary false
intellifind true
cve true

threat-command-mention-search


Search for strings in the scrapes database.

Base Command

threat-command-mention-search

Input

Argument Name Description Required
search Search using simple keywords (you can choose the search keywords by the outputs keywords), basic operators, search operators, and by document type. Basic operators: Use AND, OR, NOT, and (). For example: Searching for “bin_number: 1234 AND email_user_name: john_smith” returns all results that contain this BIN number and that username as the email user name, Searching for “comment_number: 17 AND author: gyber” returns all results with 17 comments and the author is Gyber. . Required
report_date Supply time-frame. For example: 2022-12-25T08:38:06Z. Optional
page_number Zero-based page number. 15 results per page. Default is 0. Optional
source_types A comma-separated list of source types to filter. Possible values are: Social Media, Paste Site, Hacking Forum, Instant Message, Black Market, Cyber Security Blog, Web Page. Optional
only_dark_web Show only mentions from the dark web or not. Possible values are: true, false. Optional
highlight_tags Show highlight tags (<em>) in the content or not. Possible values are: true, false. Default is True. Optional

Context Output

Path Type Description
ThreatCommand.Mentions.author String Mention author.
ThreatCommand.Mentions.comment_number Number Mentions comments number.
ThreatCommand.Mentions.original_url String Mentions original URL.
ThreatCommand.Mentions.source_date Date Mentions source date.
ThreatCommand.Mentions.url String Mention URL.
ThreatCommand.Mentions.insertion_date Date Mention insertion date.
ThreatCommand.Mentions.type String Mention type.
ThreatCommand.Mentions.Tags.is_product_for_sale Boolean Whether the product for sale.
ThreatCommand.Mentions.Tags.credit_cards Boolean Whether the mention includes credit cards.
ThreatCommand.Mentions.Tags.domains Boolean Whether the mention includes domains.
ThreatCommand.Mentions.Tags.emails Boolean Whether the mention includes emails.
ThreatCommand.Mentions.Tags.ips Boolean Whether the mention includes IPs.
ThreatCommand.Mentions.Tags.ssns Boolean Whether the mention includes SSNs (Switched Service Networks).
ThreatCommand.Mentions.Tags.urls Boolean Whether the mention includes URLs.
ThreatCommand.Mentions.id String Mention ID.
ThreatCommand.Mentions.short_content String Mention short content.
ThreatCommand.Mentions.title String Mention title.
ThreatCommand.Mentions.date Date Mention date.

Command example

!threat-command-mention-search search=test.com

Context Example

{
    "ThreatCommand": {
        "Mentions": [
            {
                "Tags": {
                    "credit_cards": false,
                    "domains": false,
                    "emails": false,
                    "ips": false,
                    "ssns": false,
                    "urls": false
                },
                "author": "jamedoefo",
                "comment_number": 321,
                "date": "2023-05-04T10:20:02",
                "id": "1234",
                "insertion_date": "2023-05-04T09:55:46.794664",
                "original_url": "https://cybercarders.com/threads/onlyfans-lana-rhoades-3gb-update.222455/unread",
                "short_content": "i was here",
                "source_date": "2023-05-04T10:20:02",
                "title": "",
                "type": "comment",
                "url": "https://cybercarders.com/threads/onlyfans-lana-rhoades-3gb-update.222455/page-33"
            },
            {
                "Tags": {
                    "credit_cards": false,
                    "domains": true,
                    "emails": false,
                    "ips": false,
                    "ssns": false,
                    "urls": true
                },
                "author": "anon",
                "comment_number": 48,
                "date": "2023-05-04T10:17:00",
                "id": "f15c68c9c4d8a4ccc7efc21373f228a7f9d7826a",
                "insertion_date": "2023-05-04T10:09:30.652547",
                "original_url": "https://www.wilderssecurity.com/threads/brave-browser-discussion-update-thread.388288/unread",
                "short_content": "brave v1.51.110 (may 3, 2023) \nhttps://brave.com/latest/\n\nspoiler: release notes v1.51.110 (may 3, 2023)\nrelease notes v1.51.110 (may 3, 2023)\nweb3\n\nadded the ability to set brave wallet permission duration when connecting to dapps. (#28841)\n[security] prevent blind cross chain signing as reported o",
                "source_date": "2023-05-04T10:17:00",
                "title": "",
                "type": "comment",
                "url": "https://www.wilderssecurity.com/threads/brave-browser-discussion-update-thread.388288/page-36"
            },
            {
                "Tags": {
                    "credit_cards": false,
                    "domains": false,
                    "emails": false,
                    "ips": false,
                    "is_product_for_sale": false,
                    "ssns": false,
                    "urls": false
                },
                "author": "aleksandermachulin",
                "date": "2023-05-04T10:16:18",
                "id": "1234",
                "insertion_date": "2023-05-04T10:21:44.790150",
                "short_content": "test",
                "source_date": "2023-05-04T10:16:18",
                "title": "test",
                "type": "paste",
                "url": "https://test.com/z2sZCecJ"
            },
            {
                "Tags": {
                    "credit_cards": false,
                    "domains": false,
                    "emails": false,
                    "ips": false,
                    "ssns": false,
                    "urls": false
                },
                "author": "no_author",
                "date": "2023-05-04T10:16:08",
                "id": "01b2a09ab8abab28f48c44aef1d3cce141cc1131",
                "insertion_date": "2023-05-04T10:21:45.660025",
                "short_content": "#include <iostream>\r\n\r\nusing namespace std;\r\n\r\nstruct nod{\r\n    int info;\r\n    nod * urm;\r\n};\r\n\r\nint cmmdc(int a , int b)\r\n{\r\n    int r;\r\n    if(b == 0) return a;\r\n    return cmmdc(b , a % b);\r\n}\r\n\r\nint numarare(nod *p)\r\n{\r\n    int perechi = 0;\r\n    for(nod *q  = p ; q -> urm ; q = q -> urm)\r\n      ",
                "source_date": "2023-05-04T10:16:08",
                "title": "untitled",
                "type": "paste",
                "url": "https://test.com/tQ4pR7pi"
            },
            {
                "Tags": {
                    "credit_cards": false,
                    "domains": false,
                    "emails": false,
                    "ips": false,
                    "ssns": false,
                    "urls": false
                },
                "author": "no_author",
                "date": "2023-05-04T10:16:05",
                "id": "0b847ec3750cf77211057d978a50226a4a6aba8b",
                "insertion_date": "2023-05-04T10:21:46.495238",
                "short_content": "To navigate from a SwiftUI view wrapped in a `UIHostingController` to another `UIViewController`, you can use a custom `UIViewControllerRepresentable`. This approach allows you to create a bridge between SwiftUI and UIKit components. Here's a step-by-step process to achieve this:\r\n\r\n1. First, create",
                "source_date": "2023-05-04T10:16:05",
                "title": "untitled",
                "type": "paste",
                "url": "https://test.com/bQcx0nuj"
            },
            {
                "Tags": {
                    "credit_cards": false,
                    "domains": false,
                    "emails": false,
                    "ips": false,
                    "ssns": false,
                    "urls": false
                },
                "author": "juanliraz",
                "comment_number": 28,
                "date": "2023-05-04T10:16:01",
                "id": "c61a9a37a18baef534d0cece9cd1e28207e75b5a",
                "insertion_date": "2023-05-04T10:09:12.482796",
                "original_url": "https://cybercarders.com/threads/heart-sender-3-0-33-full-clean-all-other-sources-are-fake-contains-malware.233594/unread",
                "short_content": "checking",
                "source_date": "2023-05-04T10:16:01",
                "title": "",
                "type": "comment",
                "url": "https://cybercarders.com/threads/heart-sender-3-0-33-full-clean-all-other-sources-are-fake-contains-malware.233594/page-3"
            },
            {
                "Tags": {
                    "credit_cards": false,
                    "domains": true,
                    "emails": false,
                    "ips": false,
                    "ssns": false,
                    "urls": true
                },
                "author": "no_author",
                "date": "2023-05-04T10:15:56",
                "id": "6a6c18dba343a6446070f47a07c68135f0005ee1",
                "insertion_date": "2023-05-04T10:21:47.505657",
                "short_content": "/*************************************************** \r\n  This is an example for the Adafruit VS1053 Codec Breakout\r\n\r\n  Designed specifically to work with the Adafruit VS1053 Codec Breakout \r\n  ----> https://www.adafruit.com/products/1381\r\n\r\n  Adafruit invests time and resources providing this open ",
                "source_date": "2023-05-04T10:15:56",
                "title": "basicplayeronesp32",
                "type": "paste",
                "url": "https://test.com/qwcJVs8E"
            },
            {
                "Tags": {
                    "credit_cards": false,
                    "domains": true,
                    "emails": false,
                    "ips": false,
                    "ssns": false,
                    "urls": true
                },
                "author": "no_author",
                "date": "2023-05-04T10:15:49",
                "id": "d0a330840ac6908ce40fe7692b6151011a2334e7",
                "insertion_date": "2023-05-04T10:21:48.530660",
                "short_content": "const axios = require('axios');\r\n\r\nmodule.exports = {\r\n config: {\r\n name: \"binary\",\r\n aliases: [\"bin\"],\r\n version: \"1.0\",\r\n author: \"shinpei\",\r\n countDown: 0,\r\n role: 0,\r\n shortDescription: {\r\n en: \"Converts text to binary.\"\r\n },\r\n longDescription: {\r\n en: \"Converts text to binary using an API.\"\r\n }",
                "source_date": "2023-05-04T10:15:49",
                "title": "untitled",
                "type": "paste",
                "url": "https://test.com/6Gm6jjGG"
            },
            {
                "Tags": {
                    "credit_cards": false,
                    "domains": true,
                    "emails": false,
                    "ips": true,
                    "ssns": false,
                    "urls": false
                },
                "author": "no_author",
                "date": "2023-05-04T10:15:42",
                "id": "f0e20e7cf875b7d0d6cc042014ec1a3dcff6e3e6",
                "insertion_date": "2023-05-04T10:21:49.433871",
                "short_content": "##\r\n# Host Database\r\n#\r\n# localhost is used to configure the loopback interface\r\n# when the system is booting.  Do not change this entry.\r\n##\r\n127.0.0.1    localhost\r\n255.255.255.255    broadcasthost\r\n::1             localhost\r\n# Added by Docker Desktop\r\n# To allow the same kube context to work on t",
                "source_date": "2023-05-04T10:15:42",
                "title": "untitled",
                "type": "paste",
                "url": "https://test.com/0Te6vfhK"
            },
            {
                "Tags": {
                    "credit_cards": false,
                    "domains": true,
                    "emails": false,
                    "ips": false,
                    "ssns": false,
                    "urls": false
                },
                "author": "no_author",
                "date": "2023-05-04T10:15:32",
                "id": "f908cce77843dd1f974281d5e5ea67d43114c016",
                "insertion_date": "2023-05-04T10:21:50.308696",
                "short_content": "[12:08:46 ERROR]: test v10.0.33\r\njava.lang.NoSuchMethodError: org.bukkit.World.getGameTime()J\r\n        at me.libraryaddict.disguise.utilities.DisguiseUtilities.setPlayerVelocity(DisguiseUtilities.java:556) ~[?:?]\r\n        at me.libraryaddict.disgu",
                "source_date": "2023-05-04T10:15:32",
                "title": "untitled",
                "type": "paste",
                "url": "https://test.com/GHNnERD4"
            },
            {
                "Tags": {
                    "credit_cards": false,
                    "domains": false,
                    "emails": false,
                    "ips": true,
                    "ssns": false,
                    "urls": false
                },
                "author": "no_author",
                "date": "2023-05-04T10:15:18",
                "id": "60e0bdce36800a3539b03ef010345d943d5669c4",
                "insertion_date": "2023-05-04T10:21:51.176037",
                "short_content": "test",
                "source_date": "2023-05-04T10:15:18",
                "title": "untitled",
                "type": "paste",
                "url": "https://test.com/uL32rurg"
            },
            {
                "Tags": {
                    "credit_cards": false,
                    "domains": false,
                    "emails": false,
                    "ips": false,
                    "ssns": false,
                    "urls": false
                },
                "author": "no_author",
                "date": "2023-05-04T10:15:11",
                "id": "3fc8bf2c1c67a61c8f35b0dd188ec555a629c6fa",
                "insertion_date": "2023-05-04T10:21:52.029357",
                "short_content": "Yeet",
                "source_date": "2023-05-04T10:15:11",
                "title": "password",
                "type": "paste",
                "url": "https://test.com/ypvSpgA8"
            },
            {
                "Tags": {
                    "credit_cards": false,
                    "domains": false,
                    "emails": false,
                    "ips": true,
                    "ssns": false,
                    "urls": false
                },
                "author": "no_author",
                "date": "2023-05-04T10:15:06",
                "id": "f51f0fb266db888d946f8206ac82057e38dde44a",
                "insertion_date": "2023-05-04T10:21:52.895423",
                "short_content": "absl-py==1.4.0\r\naiofiles==23.1.0\r\naiohttp==3.8.4\r\naiosignal==1.3.1\r\naltair==4.2.2\r\nanyio @ file:///home/conda/feedstock_root/build_artifacts/anyio_1666191106763/work/dist\r\nappdirs==1.4.4\r\nargon2-cffi @ file:///home/conda/feedstock_root/build_artifacts/argon2-cffi_1640817743617/work\r\nargon2-cffi-bind",
                "source_date": "2023-05-04T10:15:06",
                "title": "untitled",
                "type": "paste",
                "url": "https://test.com/dp4wF6MR"
            },
            {
                "Tags": {
                    "credit_cards": false,
                    "domains": true,
                    "emails": false,
                    "ips": false,
                    "ssns": false,
                    "urls": false
                },
                "author": "no_author",
                "date": "2023-05-04T10:15:02",
                "id": "f55651764e3c6c05376f7e38cf6555f64fc23158",
                "insertion_date": "2023-05-04T10:21:53.834800",
                "short_content": "[10:13:58 WARN]: [org.javacord.core.util.gateway.DiscordWebSocketAdapter] Websocket error!\r\ncom.neovisionaries.ws.client.WebSocketException: Flushing frames to the server failed: Connection or outbound has closed\r\n        at com.neovisionaries.ws.client.WritingThread.doFlush(WritingThread.java:434) ",
                "source_date": "2023-05-04T10:15:02",
                "title": "untitled",
                "type": "paste",
                "url": "https://test.com/pK0YYRsa"
            },
            {
                "Tags": {
                    "credit_cards": false,
                    "domains": false,
                    "emails": false,
                    "ips": false,
                    "ssns": false,
                    "urls": false
                },
                "author": "bellgamin",
                "comment_number": 33,
                "date": "2023-05-04T10:15:00",
                "id": "a6f37b218dad85e7472d11b3332546ad985cd46c",
                "insertion_date": "2023-05-04T09:23:49.643335",
                "original_url": "https://www.wilderssecurity.com/threads/laptop-battery-question.451238/unread",
                "short_content": "thanks for the comments bill. live long & prosper.\n\nas to \"...when you might want to turn off smart charging\" -- i quoted that part of the ms article in the comment where i linked to the ms article. ms is stating a few exceptions to ms's implicit rule, and that implicit rule is: \"turn on smart charg",
                "source_date": "2023-05-04T10:15:00",
                "title": "",
                "type": "comment",
                "url": "https://www.wilderssecurity.com/threads/laptop-battery-question.451238/page-2"
            }
        ]
    }
}

Human Readable Output

Mentions for “test.com” (page number 0)

Author Original Url Url Type Id Short Content Title Date
jamedoefo https://cybercarders.com/threads/onlyfans-lana-rhoades-3gb-update.222455/unread https://cybercarders.com/threads/onlyfans-lana-rhoades-3gb-update.222455/page-33 comment 1234 i was here   2023-05-04T10:20:02
anon https://www.wilderssecurity.com/threads/brave-browser-discussion-update-thread.388288/unread https://www.wilderssecurity.com/threads/brave-browser-discussion-update-thread.388288/page-36 comment f15c68c9c4d8a4ccc7efc21373f228a7f9d7826a brave v1.51.110 (may 3, 2023)
https://brave.com/latest/

spoiler: release notes v1.51.110 (may 3, 2023)
release notes v1.51.110 (may 3, 2023)
web3

added the ability to set brave wallet permission duration when connecting to dapps. (#28841)
[security] prevent blind cross chain signing as reported o
  2023-05-04T10:17:00

threat-command-mssp-customer-list


Get all Managed Security Service Provider’s (MSSP) sub-accounts.

Base Command

threat-command-mssp-customer-list

Input

Argument Name Description Required
limit The maximum number of records to retrieve. Default is 50. Optional
all_result Show all results if True. Possible values are: true, false. Optional

Context Output

Path Type Description
ThreatCommand.MsspCustomer.id String Customer ID.
ThreatCommand.MsspCustomer.company_name String Customer company name.
ThreatCommand.MsspCustomer.status String Customer status.
ThreatCommand.MsspCustomer.note String Customer note.

Command example

!threat-command-mssp-customer-list limit=1

Context Example

{
    "ThreatCommand": {
        "MsspCustomer": {
            "company_name": "Demo - Qmasters",
            "id": "59490ca49b655c027458d115",
            "note": "test",
            "status": "Enabled"
        }
    }
}

Human Readable Output

MSSP customer list

Id Company Name Status Note
59490ca49b655c027458d115 Demo - Qmasters Enabled test

threat-command-mssp-user-list


Get the details of the MSSPs users (In case you are an MSSP account).

Base Command

threat-command-mssp-user-list

Input

Argument Name Description Required
limit The maximum number of records to retrieve. Default is 50. Optional
all_result Show all results if True. Possible values are: true, false. Optional

Context Output

Path Type Description
ThreatCommand.MsspUser.id String User ID.
ThreatCommand.MsspUser.email String User email.
ThreatCommand.MsspUser.role String User role.
ThreatCommand.MsspUser.is_deleted String Whether the user was deleted.

Command example

!threat-command-mssp-user-list limit=1

Context Example

{
    "ThreatCommand": {
        "MsspUser": {
            "email": "test@test.com",
            "id": "64214bc94c75609d09ebb56a",
            "is_deleted": false,
            "role": "Admin"
        }
    }
}

Human Readable Output

MSSP user list

Id Email Role Is Deleted
64214bc94c75609d09ebb56a test@test.com Admin false

threat-command-account-user-list


List the users in your account. Mainly used to assign alerts.

Base Command

threat-command-account-user-list

Input

Argument Name Description Required
user_type Type of the user. Possible values are: Admin, Analyst. Optional
user_email Email of the user. Optional
user_id The ID of the user. Optional
limit The maximum number of records to retrieve. Default is 50. Optional
all_result Show all results if True. Possible values are: true, false. Optional

Context Output

Path Type Description
ThreatCommand.AccountUser.id String User ID.
ThreatCommand.AccountUser.email String User email.
ThreatCommand.AccountUser.first_name String User first name.
ThreatCommand.AccountUser.last_name String User last name.
ThreatCommand.AccountUser.role String User role.
ThreatCommand.AccountUser.is_deleted String Whether the user was deleted.

Command example

!threat-command-account-user-list limit=1

Context Example

{
    "ThreatCommand": {
        "AccountUser": {
            "email": "test@test.com",
            "first_name": "test",
            "id": "59490cd818a3b902664b4ed7",
            "is_deleted": false,
            "last_name": "test",
            "permissions": {
                "Automation": {
                    "Extend": true,
                    "Integrations": true,
                    "Policy": true,
                    "Profiler": true
                },
                "Configurations": {
                    "PhishingWatchManager": true
                },
                "Data": {
                    "Actions": {
                        "AskTheAnalyst": true,
                        "Assignment": true,
                        "ChangeSeverity": true,
                        "ChangeStatus": true,
                        "Remediation": {
                            "Report": true,
                            "Takedown": true
                        },
                        "Share": true
                    },
                    "AlertTypes": {
                        "AttackIndication": true,
                        "BrandSecurity": true,
                        "DataLeakage": true,
                        "ExploitableData": true,
                        "Phishing": true,
                        "vip": true
                    },
                    "Assets": {
                        "Edit": true,
                        "View": true
                    },
                    "Reports": {
                        "View": true
                    },
                    "StrategicInsights": {
                        "Edit": true,
                        "View": true
                    }
                },
                "TIP": {
                    "EditSources": true,
                    "IntelliFind": true,
                    "InvestigationPage": true,
                    "ThreatLibrary": true,
                    "View": true
                },
                "ThreatThirdParty": {
                    "RiskAssessment": {
                        "Assess": true,
                        "View": true
                    },
                    "TailoredRisk": {
                        "Assess": true,
                        "View": true
                    }
                },
                "Vulnerabilities": {
                    "View": true
                }
            },
            "role": "Admin"
        }
    }
}

Human Readable Output

Account user list

Id Email First Name Last Name Role Is Deleted
59490cd818a3b902664b4ed7 test@test.com test test Admin false

threat-command-alert-type-list


List alert types and sub-types. They are mainly used to add manual alerts.

Base Command

threat-command-alert-type-list

Input

Argument Name Description Required
limit The maximum number of records to retrieve. Default is 50. Optional
all_result Show all results if True. Possible values are: true, false. Optional

Context Output

Path Type Description
ThreatCommand.AlertType.type String Type.
ThreatCommand.AlertType.sub_type String Sub-type of the type.

Command example

!threat-command-alert-type-list limit=1

Context Example

{
    "ThreatCommand": {
        "AlertType": {
            "sub_type": "VulnerabilityInTechnologyInUse",
            "type": "ExploitableData"
        }
    }
}

Human Readable Output

Alert types

Type Sub Type
ExploitableData VulnerabilityInTechnologyInUse

threat-command-alert-source-type-list


List alert source types. They are mainly used to add manual alerts.

Base Command

threat-command-alert-source-type-list

Input

Argument Name Description Required
limit The maximum number of records to retrieve. Default is 50. Optional
all_result Show all results if True. Possible values are: true, false. Optional

Context Output

Path Type Description
ThreatCommand.AlertSourceType String List of source types.

Command example

!threat-command-alert-source-type-list limit=1

Context Example

{
    "ThreatCommand": {
        "AlertSourceType": [
            "Application Store"
        ]
    }
}

Human Readable Output

Alert source types

Source Type
Application Store

threat-command-alert-scenario-list


List alert scenarios. They are mainly used to add manual alerts.

Base Command

threat-command-alert-scenario-list

Input

Argument Name Description Required
limit The maximum number of records to retrieve. Default is 50. Optional
all_result Show all results if True. Possible values are: true, false. Optional
type Alert type (dependencies - use threat-command-alert-type-list command to get all the alert types). Possible values are: Attack Indication, Data Leakage, Phishing, Brand Security, Exploitable Data, vip. Optional
sub_type Alert’s sub-type (dependencies - use threat-command-alert-type-list command to get all the alert subtypes). Optional

Context Output

Path Type Description
ThreatCommand.Scenario.type String Alert type.
ThreatCommand.Scenario.subtype String Alert sub-type.
ThreatCommand.Scenario.scenario String Name of the scenario.
ThreatCommand.Scenario.description String Short description of the scenario.

Command example

!threat-command-alert-scenario-list limit=1

Context Example

{
    "ThreatCommand": {
        "Scenario": {
            "description": "A company email address reported as spamming",
            "scenario": "ACompanyEmailAddressReportedAsMalicious",
            "subtype": "AssetReportedAsMalicious",
            "type": "AttackIndication"
        }
    }
}

Human Readable Output

Alert scenario list

Scenario Description Type Subtype
ACompanyEmailAddressReportedAsMalicious A company email address reported as spamming AttackIndication AssetReportedAsMalicious

file


Runs reputation on files.

Base Command

file

Input

Argument Name Description Required
unfinished_enriches Unfinished IOCs number. Default is -1. Required
file Hash of the file to query. Supports MD5, SHA1, and SHA256. Required
interval_in_seconds The interval in seconds between each poll. Default is 30. Optional
timeout_in_seconds The timeout in seconds until polling ends. Default is 600. Optional

Context Output

Path Type Description
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.sha512 String The SHA512 hash of the file.
File.name String The full file name (including file extension).
File.description String The description of the file.
File.size String The size of the file.
File.file_type String The type of the file.
File.tags String The tags of the file.
File.actor String Related threat actors to the file.
File.campaign String Related threat campaigns to the file.
File.associated_file_names String Assosiated file names to the file.
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.Reliability String Reliability of the source providing the intelligence data.
DBotScore.Score Number The actual score.

ip


Checks the reputation of an IP address.

Base Command

ip

Input

Argument Name Description Required
unfinished_enriches Unfinished IOCs number. Default is -1. Required
ip IP address to check. Required
interval_in_seconds The interval in seconds between each poll. Default is 30. Optional
timeout_in_seconds The timeout in seconds until polling ends. Default is 600. Optional

Context Output

Path Type Description
DBotScore.Indicator String The indicator that was tested.
DBotScore.Reliability String Reliability of the source providing the intelligence data.
DBotScore.Score Number The actual score.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the score.
IP.ASN String IP ASN.
IP.Address String IP address.
IP.Region String IP region.
IP.UpdatedDate String IP updated date.
ThreatCommand.IP.asn String IP ASN.
ThreatCommand.IP.ip String IP address.
ThreatCommand.IP.region String IP region.
ThreatCommand.IP.updated_date String IP updated date.

url


Checks the reputation of a URL.

Base Command

url

Input

Argument Name Description Required
unfinished_enriches Unfinished IOCs number. Default is -1. Required
url A comma-separated list of URLs to check. This command will not work properly on URLs containing commas. Required
sampleSize The number of samples from each type (resolutions, detections, etc.) to display for long format. Default is 10. Optional
interval_in_seconds The interval in seconds between each poll. Default is 30. Optional
timeout_in_seconds The timeout in seconds until polling ends. Default is 600. Optional

Context Output

Path Type Description
DBotScore.Indicator String The indicator that was tested.
DBotScore.Reliability String Reliability of the source providing the intelligence data.
DBotScore.Score Number The actual score.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the score.
URL.Data String The URL value.
URL.DetectionEngines String URL detection engines.
URL.PositiveDetections Number Number of positive engines.
URL.Tags Number URL tags.
ThreatCommand.URL.detection_engines String URL detection engines.
ThreatCommand.URL.positive_detections String URL positive detection engines.
ThreatCommand.URL.tags String URL tags.
ThreatCommand.URL.url Number The URL value.

domain


Checks the reputation of a domain.

Base Command

domain

Input

Argument Name Description Required
unfinished_enriches Unfinished IOCs number. Default is -1. Required
domain Domain name to check. Required
interval_in_seconds The interval in seconds between each poll. Default is 30. Optional
timeout_in_seconds The timeout in seconds until polling ends. Default is 600. Optional

Context Output

Path Type Description
Domain.domain String Domain found.
Domain.Name String The name of the domain that was checked.
DBotScore.Indicator String The indicator that was tested.
DBotScore.Reliability String Reliability of the source providing the intelligence data.
DBotScore.Score Number The actual score.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the score.
Domain.DNSRecords String DNS records of the domain.
ThreatCommand.Domain.domain String The domain value.
ThreatCommand.Domain.sub_domains Date Sub domains of the domain.
ThreatCommand.Domain.tags String Tags of the domain.
ThreatCommand.Domain.updated_date String Domain updated date.

Configuration parameters

  • base_url — Server URL (required)
  • credentials — Account ID (required)
  • integrationReliability — Source Reliability (required)
  • isFetch — Fetch incidents
  • first_fetch — First fetch timestamp.
  • max_fetch — Maximum incidents per fetch (required)
  • alert_types — Alert types to fetch as incidents
  • network_types — Network types to fetch as incidents
  • alert_severity — Minimum Alert Severity Level
  • source_types — Source types to filter alerts by
  • fetch_closed_incidents — Fetch closed alerts
  • fetch_csv — Include CSV files of alerts
  • fetch_attachments — Include attachments of alerts
  • mssp_sub_account — Sub-account ID (for MSSP accounts).
  • incidentType — Incident type
  • incidentFetchInterval — Incidents Fetch Interval
  • proxy — Use system proxy settings
  • insecure — Trust any certificate (not secure)

Commands (56)

  • domain

    Checks the reputation of a domain.

  • file

    Runs reputation on files.

  • ip

    Checks the reputation of an IP address.

  • threat-command-account-system-modules-list

    List the system modules of your account.

  • threat-command-account-user-list

    List the users in your account. Mainly used to assign alerts.

  • threat-command-account-whitelist-remove

    Reverts IOC values to the system-default whitelist status. The ETP Suite automatically whitelists certain IOCs, such as company assets. You can override this designation or ensure that certain IOCs will not be system whitelisted using the threat-command-account-whitelist-update command. There is no indication of success or failure for this command. The user has to choose a correct and existing IOC. At least one IOC is required.

  • threat-command-account-whitelist-update

    You can add an IOC to your user whitelist (even if it is already on the system whitelist). If you change your mind, you can then revert that decision to rely again on the system designation using the threat-command-account-whitelist-remove command. When an IOC is whitelisted, it will not be sent to integrated security to block. When an IOC is not whitelisted, it will be sent to integrated security devices to block. There is no indication of success or failure for this command. The user has to choose a correct and existing IOC. At least one IOC is required.

  • threat-command-alert-activity-log-get

    Get alert activity log.

  • threat-command-alert-analyst-ask

    Send a question to an analyst about the requested alert. Questions can revolve around an alert explanation, a request for more context, recommended remediation steps, or requests for threat actor engagement. In order to get the conversation with the analyst, use the threat-command-alert-analyst-conversation-list command.

  • threat-command-alert-analyst-conversation-list

    Get alert's analyst response.

  • threat-command-alert-assign

    Assign an alert to other ETP Suite users. When an alert is assigned, the assignee will receive a notification. Mainly used to assign alerts.

  • threat-command-alert-blocklist-get

    Get alert's blocklist status.

  • threat-command-alert-blocklist-update

    Change selected IOCs blocklist status.

  • threat-command-alert-close

    Close alert.

  • threat-command-alert-create

    Create a new alert. You have to insert scenario or type and sub_type.

  • threat-command-alert-csv-get

    Get alert's CSV file in case of credentials leakage or leaked credit cards alerts.

  • threat-command-alert-image-list

    List alert images by ID.

  • threat-command-alert-ioc-report

    Report IOCs to external sources (Report the URLs and domains that are included in an alert to external sources. This can warn others of the potential danger of those IOCs).

  • threat-command-alert-list

    Get a list of alerts with all details.

  • threat-command-alert-note-add

    Add a note to the alert. You can add notes, as text or uploaded files, to an alert that can be seen by internal users. Each note is accompanied by the name of the note creator. Other users can reply to notes. Alert notes remain with the alert, even after it is closed or otherwise remediated.

  • threat-command-alert-reopen

    Reopen alert.

  • threat-command-alert-scenario-list

    List alert scenarios. They are mainly used to add manual alerts.

  • threat-command-alert-send-mail

    Send mail with the alert details and a question.

  • threat-command-alert-severity-update

    Change the alert's severity. Changing the severity level of alerts can help to prioritize alert management.

  • threat-command-alert-source-type-list

    List alert source types. They are mainly used to add manual alerts.

  • threat-command-alert-tag-add

    Adds a tag to an alert. This enables you to classify alerts and later search for all alerts with a specific tag.

  • threat-command-alert-tag-remove

    Removes a tag from the alert.

  • threat-command-alert-takedown-request

    Send a takedown request for the selected alert (Request that Threat Command will contact the host to request a takedown of a malicious domain, website, or mobile application).

  • threat-command-alert-takedown-request-status-get

    Get the alert's takedown status.

  • threat-command-alert-type-list

    List alert types and sub-types. They are mainly used to add manual alerts.

  • threat-command-alert-unassign

    Unassign an alert from all users.

  • threat-command-asset-add

    Add assets by type and value. Assets include any company resource that could lead to a potential security threat.

  • threat-command-asset-delete

    Delete asset by type and value.

  • threat-command-asset-list

    Get account assets grouped by asset type.

  • threat-command-asset-type-list

    Get all asset types. Mainly used to add or delete assets.

  • threat-command-cve-add

    Add CVEs to account.

  • threat-command-cve-delete

    Delete CVEs from account.

  • threat-command-cve-list

    Get CVE's list from account.

  • threat-command-cyber-term-cve-list

    List cyber term CVEs by cyber term ID.

  • threat-command-cyber-term-ioc-list

    List cyber term IOCs by cyber term ID.

  • threat-command-cyber-term-list

    List cyber terms by filter.

  • threat-command-enrichment-quota-usage

    Gets the current API enrichment credits ("quota") usage for the requester account.

  • threat-command-ioc-blocklist-add

    Adds an IOC to an internal Remediation Blocklist. By sending the blocklist to security devices, you can block the IOCs. At least one IOC is required.

  • threat-command-ioc-blocklist-remove

    Removes IOC values from the Remediation blocklist. There is no indication of success or failure for this command. The user has to choose a correct and existing IOC. At least one IOC is required.

  • threat-command-ioc-comment-add

    Adds comments to IOCs. At least one IOC is required.

  • threat-command-ioc-search

    Gets IOC details by value or IOC's full enrichment data. While using the enrichment flag, the command is scheduled and allows us to get full enrichment data. Note that enrichment has a quota. You can get the quota by using threat-command-quotas-usage-get.

  • threat-command-ioc-severity-update

    Changes the severity of existing IOCs for the requester account (overrides the system severity). At least one IOC is required.

  • threat-command-ioc-tags-add

    Adds user tags to IOCs. This enables you to classify IOCs and later search for all IOCs with a specific tag. There is no indication of success or failure for this command. The user has to choose a correct and existing IOC.

  • threat-command-mention-search

    Search for strings in the scrapes database.

  • threat-command-mssp-customer-list

    Get all Managed Security Service Provider's (MSSP) sub-accounts.

  • threat-command-mssp-user-list

    Get the details of the MSSPs users (In case you are an MSSP account).

  • threat-command-source-document-create

    Adds a new IOC source document. At least one IOC is required.

  • threat-command-source-document-delete

    Deletes an existing IOC source document.

  • threat-command-source-document-ioc-create

    Create new IOCs to existing IOC source documents. At least one IOC is required.

  • threat-command-source-list

    Gets lists of IOC document sources.

  • url

    Checks the reputation of a URL.

import copy
import csv
import pathlib
import re
from collections.abc import Callable
from enum import Enum, StrEnum
from http import HTTPStatus
from typing import Any, cast

import demistomock as demisto  # noqa: F401
from CommonServerPython import *  # noqa: F401
from requests import Response

DEFAULT_INTERVAL = 30
DEFAULT_TIMEOUT = 600
ISO_8601_FORMAT = "%Y-%m-%dT%H:%M:%S.000Z"
INTEGRATION_ENTRY_CONTEXT = "ThreatCommand"
BACKOFF_FACTOR = 15  # Consider its double.
RETRIES = 3  # One retry is completed right away, so it should be viewed as a minor attempt.
STATUS_LIST_TO_RETRY = [429] + list(range(500, 600))


class Headers(list, Enum):  # type: ignore[misc]
    GET_ALERT = [
        "id",
        "type",
        "sub_type",
        "title",
        "description",
        "severity",
        "found_date",
        "is_closed",
        "Tags",
        "assignees",
    ]
    LIST_CYBER_TERM = [
        "id",
        "name",
        "severity",
        "overview",
        "target_countries",
        "sectors",
        "ttp",
        "related_malware",
        "related_campaigns",
    ]
    GET_IOC = [
        "value",
        "type",
        "status",
        "is_whitelisted",
        "score",
        "severity",
        "last_update_date",
    ]
    MENTION = [
        "author",
        "original_url",
        "url",
        "type",
        "id",
        "short_content",
        "title",
        "date",
    ]
    ENRICH_IOC = [
        "value",
        "Source",
        "status",
        "is_known_ioc",
        "update_seen",
        "is_whitelisted",
        "Severity",
    ]


class ReadableOutputs(str, Enum):
    CYBER_TERM_CVES = "Related CVEs to Cyber term {0}"
    CYBER_TERM_IOCS = "Related IOCs to Cyber term {0}"
    CYBER_TERM = "Cyber terms"
    IOC_SOURCE = "IOC sources"
    SYSTEM_MODULES = "System modules"
    ASSET_TYPES = "Asset types."
    LIST_ASSET = "Asset list."
    CREATE_ASSET = 'Asset "{0}" successfully added to "{1}" asset list.'
    DELETE_ASSET = 'Asset "{0}" successfully deleted from "{1}" asset list.'
    CREATE_IOC = 'IOC "{0}" successfully added to "{1}" document source.'
    DOCUMENT_CREATE = "Source document successfully created."
    DOCUMENT_DELETE = 'Source document "{0}" successfully deleted.'
    CREATE_IOC_SUCCESS = 'IOCs "{0}" successfully added to "{1}" source document.'
    CREATE_IOC_FAIL = 'Failed to add IOCs "{0}" to "{1}" source document.'
    CVES = "CVE list."
    CVE_NEXT_OFFSET = "CVE next offset."
    ADD_CVE_SUCCESS = 'The "{0}" CVEs successfully added.'
    ADD_CVE_FAIL = 'Failed to add the "{0}" CVEs.'
    DELETE_CVE_SUCCESS = 'The "{0}" CVEs successfully deleted.'
    DELETE_CVE_FAIL = 'Failed to delete the "{0}" CVEs.'
    ALERT_LIST = "Alert list"
    ALERT_GET = 'Alert "{0}"'
    ALERT_CREATE = "Alert successfully created"
    ALERT_CLOSE = 'Alert "{0}" successfully closed'
    ALERT_SEVERITY = 'Alert "{0}" severity successfully updated to "{1}".'
    ALERT_ASSIGN = 'Alert "{0}" successfully assign to user "{1}".'
    ALERT_UNASSIGN = "Alert '{0}' successfully unassigned from any user."
    ALERT_REOPEN = 'Alert "{0}" successfully re-opened.'
    ALERT_TAG_ADD = 'The tag "{1}" successfully added to "{0}" Alert.'
    ALERT_TAG_REMOVE = 'The tag "{1}" successfully removed from "{0}" Alert.'
    ALERT_MAIL = 'The alert "{0}" successfully send to "{1}".'
    ALERT_ANALYST = 'The alert "{0}" successfully sent to the analyst.'
    ALERT_CONVERSATION_LIST = "Alert conversation with analyst:"
    ALERT_NO_CONVERSATION_LIST = "There is no conversation with analyst."
    ALERT_ADD_NOTE = 'Note successfully add to alert "{0}".'
    ALERT_BLOCKLIST_GET = 'Blocklist for alert "{0}".'
    ALERT_BLOCKLIST_UPDATE = 'IOC successfully updated to status "{0}".'
    ALERT_IMAGES = 'Alert "{0}" Images list.'
    ALERT_NO_IMAGES = 'Alert "{0}" does not contain images.'
    ALERT_CSV = 'Alert "{0}" CSV file.'
    ALERT_NO_CSV = 'Alert "{0}" does not have a CSV file.'
    ALERT_TAKEDOWN = 'Successfully sent takedown request for alert "{0}".'
    ALERT_TAKEDOWN_STATUS = 'Takedown status for alert "{0}".'
    ALERT_REPORT = 'Alert "{0}" successfully reported'
    ALERT_ACTIVITY = 'Alert "{0}" activity log'
    ALERT_TYPES = "Alert types"
    ALERT_SOURCE_TYPES = "Alert source types"
    IOC_LIST = "IOC list"
    IOC_GET = 'IOC "{0}"'
    ENRICH_GET = 'Enrichment data for IOC "{0}"'
    IOC_TAG_ADD = 'The tags "{1}" successfully added to "{0}" IOC.'
    UPDATE_IOC_SEVERITY = 'The severity "{1}" successfully updated to "{0}" IOCs.'
    ADD_IOC_COMMENT = 'The comment "{1}" successfully updated to "{0}" IOCs.'
    UPDATE_ACCOUNT_WHITELIST = 'The status "{1}" successfully updated to "{0}" IOCs in the account whitelist.'
    REMOVE_ACCOUNT_WHITELIST = 'The IOCs "{0}" successfully removed from the account whitelist.'
    ADD_IOC_BLOCKLIST = 'The IOCs "{0}" successfully added to the remediation blocklist.'
    REMOVE_IOC_BLOCKLIST = 'The IOCs "{0}" successfully removed from the remediation blocklist.'
    ACCOUNT_USER_LIST = "Account user list"
    MSSP_USER_LIST = "MSSP user list"
    MSSP_CUSTOMER_LIST = "MSSP customer list"
    SCENARIO_LIST = "Alert scenario list"
    MENTIONS = 'Mentions for "{0}" (page number {1}).'
    ENRICH_QUOTA = "Current API enrichment credits (quota)."


class ReadableErrors(str, Enum):
    MISSING_IOCS = "Missing IOCs. Please insert."
    SOURCE_NOT_EXIST = "The source does not exist."
    GENERAL = "General error with the request."
    NOT_FOUND = "The object does not exist."
    WRONG_PARAMETERS = "Wrong parameters."
    NO_CONTENT = "No content - there is no data to show."
    UNAUTHORIZED = "Authorization Error: Make sure that the Account ID and API key are correctly set."
    ENRICH_FAIL = 'Enrichment failed. Status is "{0}"".'
    INSERT_VALUE = "Please insert {0}."
    NO_IOCS = "Please insert at least one IOC."
    WRONG_IOC = "Please insert correct IOC value."
    EMAIL = '"{0}" is not correct email, please insert correct email.'
    DOMAIN = '"{0}" is not correct domain, please insert correct domain.'
    URL = '"{0}" is not correct URL, please insert correct URL.'
    IP = '"{0}" is not correct IP, please insert correct IP.'
    HASH = '"{0}" is not correct hash, please insert correct hash.'
    SOURCE_ALREADY_EXIST = "The source already exist."
    CONFIDENCE_LEVEL = "confidence_level is a number in range 1-3"
    RATE = "rate is a number in range 0-5"
    ALERT_LIST = "You can't choose alert_id and retrieve_ids_only."
    SCENARIO_TYPES = "You have to insert scenario or type and sub-type."
    ALERT_TYPE = "You have to insert type or remove the sub_type and insert scenario."
    ALERT_SUB_TYPE = "You have to insert sub_type or remove the type and insert scenario."
    ARGUMENT = "{0} argument should be {1}"
    NUMBER = "Please insert a valid number."
    LIMIT = "Limit has to be positive number."
    MODULE_NOT_AVAILABLE = "The module is not available."
    ACCOUNT_ID_HEADER = "Missing Account ID."
    IS_HIDDEN = 'You can use is_hidden=True only in case the reason is "False Positive"'
    USER_EMAIL = "The user email is invalid."
    USER_ID = "The user ID is invalid."
    SOURCE_TYPE = "The source type is invalid."
    SUB_TYPE = "The sub-type is invalid."
    EXTERNAL_SOURCE = "The external source is invalid."
    ASSET_TYPE = "The asset type is invalid."
    TAG_ID = "The tag ID is invalid."
    ASSET_COUNTRY = "The country is invalid."
    ASSET_SECTOR = "The sector is invalid."
    ASSET_DOMAIN = "The domain is invalid."
    TAG_EXIST = "The tag is already exist."
    INVALID_EMAIL = "The email is invalid."
    IOC_NOT_EXIST = "The IOC does not exist."
    FIRST_FETCH_NOT_EXIST = "Failed to get first fetch time."
    MAX_FETCH_INVALID = "Maximum incidents per fetch must be a positive integer ranging from 1 to 200."


ERROR_RESPONSE_MAPPER: dict[str, str] = {
    "MissingIocs": ReadableErrors.MISSING_IOCS.value,
    "SourceDoesNotExist": ReadableErrors.SOURCE_NOT_EXIST.value,
    "SourceNameAlreadyExists": ReadableErrors.SOURCE_ALREADY_EXIST.value,
    "InvaliduserEmail": ReadableErrors.USER_EMAIL.value,
    "InvaliduserId": ReadableErrors.USER_ID.value,
    "InvalidAssigneeID": ReadableErrors.USER_ID.value,
    "InvalidSourceType": ReadableErrors.SOURCE_TYPE.value,
    "InvalidSubAlertType": ReadableErrors.SUB_TYPE.value,
    "InvalidExternalSources": ReadableErrors.EXTERNAL_SOURCE.value,
    "InvalidAssetType": ReadableErrors.ASSET_TYPE.value,
    "InvalidTagID": ReadableErrors.TAG_ID.value,
    "InvalidCountryOfActivityAsset": ReadableErrors.ASSET_COUNTRY.value,
    "InvalidSectorAsset": ReadableErrors.ASSET_SECTOR.value,
    "InvalidDomainAsset": ReadableErrors.ASSET_DOMAIN.value,
    "MissingAccountIdHeader": ReadableErrors.ACCOUNT_ID_HEADER.value,
    "ModuleNotAvailable": ReadableErrors.MODULE_NOT_AVAILABLE.value,
    "TagExist": ReadableErrors.TAG_EXIST.value,
    "InvalidEmails": ReadableErrors.INVALID_EMAIL.value,
    "IocDoesNotExist": ReadableErrors.IOC_NOT_EXIST.value,
}


ERROR_CODE_MAPPER: dict[int, str] = {
    HTTPStatus.NOT_FOUND: ReadableErrors.NOT_FOUND.value,
    HTTPStatus.UNPROCESSABLE_ENTITY: ReadableErrors.WRONG_PARAMETERS.value,
    HTTPStatus.INTERNAL_SERVER_ERROR: ReadableErrors.GENERAL.value,
    HTTPStatus.UNAUTHORIZED: ReadableErrors.UNAUTHORIZED.value,
    HTTPStatus.NO_CONTENT: ReadableErrors.NO_CONTENT.value,
}


class IOCType(str, Enum):
    FILE = "FILE"
    URL = "URL"
    IP = "IP"
    HASH = "HASH"
    EMAIL = "EMAIL"
    DOMAIN = "DOMAIN"


pattern_and_readable_error_by_ioc_type = {
    IOCType.URL: (urlRegex, ReadableErrors.URL),
    IOCType.IP: (ipv4Regex, ReadableErrors.IP),
    IOCType.HASH: (hashRegex, ReadableErrors.HASH),
    IOCType.EMAIL: (emailRegex, ReadableErrors.EMAIL),
}

WHITELIST_ADD = "Add to the user whitelist"
WHITELIST_DO_NOT = "Do not whitelist"


class ArgumentValues(list, Enum):  # type: ignore[misc]
    WHITELIST_STATUS = [WHITELIST_ADD, WHITELIST_DO_NOT]
    BOOLEAN = ["true", "false"]
    ALERT_TYPE = [
        "Attack Indication",
        "Data Leakage",
        "Phishing",
        "Brand Security",
        "Exploitable Data",
        "vip",
    ]
    ALERT_IOC_AND_DOCUMENT_SEVERITY = ["High", "Medium", "Low"]
    ALERT_SOURCE_NETWORK = ["Clear Web", "Dark Web"]
    ALERT_CLOSE_REASON = [
        "Problem Solved",
        "Informational Only",
        "Problem We Are Already Aware Of",
        "Company Owned Domain",
        "Legitimate Application/Profile",
        "Not Related To My Company",
        "False Positive",
        "Other",
    ]
    ALERT_BLOCKLIST = ["Sent", "Not Sent"]
    CVE_SEVERITY = ["High", "Medium", "Low", "Critical"]
    USER_TYPE = ["Admin", "Analyst"]
    MENTION_SOURCE_TYPE = [
        "Social Media",
        "Paste Site",
        "Hacking Forum",
        "Instant Message",
        "Black Market",
        "Cyber Security Blog",
        "Web Page",
    ]
    SOURCE_TYPE = [
        "Application Stores",
        "Black Market",
        "Hacking Forum",
        "Others",
        "Paste Site",
        "Social Media",
    ]


V1_PREFIX = "v1"
V2_PREFIX = "v2"
V3_PREFIX = "v3"
API_MAX_LIMIT = 1000
FETCH_LIMIT = 50
XSOAR_SEVERITY = {
    "Low": IncidentSeverity.LOW,
    "Medium": IncidentSeverity.MEDIUM,
    "High": IncidentSeverity.HIGH,
}
ALERT_WHITELIST = {
    WHITELIST_ADD: True,
    WHITELIST_DO_NOT: False,
}


class UrlPrefix(StrEnum):
    CYBER_TERM = "threat-library/cyber-terms"
    IOC_SOURCE = "iocs"
    ACCOUNT = "account"
    ASSET = "data/assets"
    CVE = "cves"
    ALERT = "data/alerts"
    IOC = "iocs"
    MSSP = "mssp"


class Parser:
    """
    This class will handle the objects input arguments API response outputs.
    """

    def cyber_term_cve_parser(self, obj: dict[str, Any]) -> dict[str, Any]:
        """
        Parse Cyber-term CVE response from the API to XSOAR outputs.

        Args:
            obj (dict[str, Any]): Cyber-term CVE response from the API.

        Returns:
            dict[str, Any]: XSOAR outputs.
        """
        return {
            "id": obj.get("CveId"),
            "publish_date": obj.get("PublishedDate"),
            "vendor_product": obj.get("VendorProducts"),
        }

    def cyber_term_ioc_parser(self, obj: dict[str, Any]) -> dict[str, Any]:
        """
        Parse Cyber-term IOC response from the API to XSOAR outputs.

        Args:
            obj (dict[str, Any]): Cyber-term IOC response from the API.

        Returns:
            dict[str, Any]: XSOAR outputs.
        """
        return {
            "value": obj.get("Value"),
            "type": obj.get("Type"),
            "updated_date": obj.get("UpdateDate"),
            "status": obj.get("Status"),
            "is_whitelisted": obj.get("Whitelisted"),
            "severity": obj.get("Severity"),
            "reporting_feeds": obj.get("ReportingFeeds"),
        }

    def cyber_term_parser(self, obj: dict[str, Any]) -> dict[str, Any]:
        """
        Parse Cyber-term response from the API to XSOAR outputs.

        Args:
            obj (dict[str, Any]): Cyber-term response from the API.

        Returns:
            dict[str, Any]: XSOAR outputs.
        """
        return {
            "id": obj.get("ID"),
            "name": obj.get("Value"),
            "type": obj.get("Type"),
            "severity": obj.get("Severity"),
            "aliases": obj.get("Aliases"),
            "origins": obj.get("Origins"),
            "target_countries": obj.get("TargetCountries"),
            "sectors": obj.get("TargetSectors"),
            "created_date": obj.get("CreatedDate"),
            "updated_date": obj.get("UpdatedDate"),
            "ttp": obj.get("TTPs"),
            "overview": obj.get("Overview"),
            "additional_information": obj.get("AdditionalInformation"),
            "related_malware": obj.get("RelatedMalware"),
            "related_threat_actor": obj.get("RelatedThreatActors"),
            "related_campaigns": obj.get("RelatedCampaigns"),
            "MitreAttack": [
                {
                    "tactic": attack.get("ReportingFeeds"),
                    "Techniques": [
                        {
                            "name": tech.get("ReportingFeeds"),
                            "url": tech.get("ReportingFeeds"),
                        }
                        for tech in attack.get("Techniques", [])
                    ],
                }
                for attack in obj.get("MitreAttack", [])
            ],
        }

    def cve_parser(self, obj: dict[str, Any]) -> dict[str, Any]:
        """
        Parse CVE response from the API to XSOAR outputs.

        Args:
            obj (dict[str, Any]): CVE response from the API.

        Returns:
            dict[str, Any]: XSOAR outputs.
        """
        return {
            "id": obj.get("cveId"),
            "cpe": [
                {
                    "value": cpe.get("Value"),
                    "title": cpe.get("Title"),
                    "vendor_product": cpe.get("VendorProduct"),
                }
                for cpe in obj.get("cpe", [])
            ],
            "published_date": obj.get("publishedDate"),
            "update_date": obj.get("updateDate"),
            "severity": obj.get("severity"),
            "intsights_score": obj.get("intsightsScore"),
            "cvss_score": obj.get("cvssScore"),
            "social_media_mentions": dict_safe_get(obj, ["mentionsPerSource", "SocialMedia"]),
            "paste_site_mentions": dict_safe_get(obj, ["mentionsPerSource", "PasteSite"]),
            "hacking_forum_mentions": dict_safe_get(obj, ["mentionsPerSource", "HackingForum"]),
            "instant_message_mentions": dict_safe_get(obj, ["mentionsPerSource", "InstantMessage"]),
            "dark_web_mentions": dict_safe_get(obj, ["mentionsPerSource", "DarkWeb"]),
            "code_repositories_mentions": dict_safe_get(obj, ["mentionsPerSource", "CodeRepositories"]),
            "exploit_mentions": dict_safe_get(obj, ["mentionsPerSource", "Exploit"]),
            "clear_web_cyber_blogs_mentions": dict_safe_get(obj, ["mentionsPerSource", "ClearWebCyberBlogs"]),
            "poc_mentions": dict_safe_get(obj, ["mentionsPerSource", "POC"]),
            "first_mention_date": obj.get("firstMentionDate"),
            "last_mention_date": obj.get("lastMentionDate"),
            "exploit_availability": obj.get("exploitAvailability"),
            "vulnerability_origin": obj.get("vulnerabilityOrigin"),
            "related_threat_actors": obj.get("relatedThreatActors"),
            "related_malware": obj.get("relatedMalware"),
            "related_campaigns": obj.get("relatedCampaigns"),
        }

    def alert_get_parser(self, obj: dict[str, Any]) -> dict[str, Any]:
        """
        Parse complete Alert response from the API to XSOAR outputs.

        Args:
            obj (dict[str, Any]): Alert response from the API.

        Returns:
            dict[str, Any]: XSOAR outputs.
        """
        return {
            "id": obj.get("_id"),
            "assets": [
                {
                    "type": asset.get("Type"),
                    "value": asset.get("Value"),
                }
                for asset in obj.get("Assets", [])
            ],
            "assignees": obj.get("Assignees"),
            "type": dict_safe_get(obj, ["Details", "Type"]),
            "sub_type": dict_safe_get(obj, ["Details", "SubType"]),
            "title": dict_safe_get(obj, ["Details", "Title"]),
            "description": dict_safe_get(obj, ["Details", "Description"]),
            "severity": dict_safe_get(obj, ["Details", "Severity"]),
            "images": dict_safe_get(obj, ["Details", "Images"]),
            "source_type": dict_safe_get(obj, ["Details", "Source", "Type"]),
            "source_url": str(dict_safe_get(obj, ["Details", "Source", "URL"], "")),
            "source_email": "",
            "source_network_type": dict_safe_get(obj, ["Details", "Source", "NetworkType"]),
            "source_date": str(dict_safe_get(obj, ["Details", "Source", "Date"], "")),
            "Tags": [
                {
                    "created_by": tag.get("CreatedBy"),
                    "name": tag.get("Name"),
                    "id": tag.get("_id"),
                }
                for tag in dict_safe_get(obj, ["Details", "Tags"], [])
            ],
            "related_iocs": obj.get("RelatedIocs"),
            "found_date": obj.get("FoundDate"),
            "update_date": obj.get("UpdateDate"),
            "takedown_status": obj.get("TakedownStatus"),
            "is_closed": dict_safe_get(obj, ["Closed", "IsClosed"]),
            "is_flagged": obj.get("IsFlagged"),
            "related_threat_ids": obj.get("RelatedThreatIDs"),
        }

    def alert_fetch_parser(self, obj: dict[str, Any]) -> dict[str, Any]:
        """
        Parse complete Alert response from the API to fetch XSOAR outputs.

        Args:
            obj (dict[str, Any]): Alert response from the API.

        Returns:
            dict[str, Any]: fetch XSOAR outputs.
        """
        return remove_empty_elements(
            {
                "id": obj.get("_id"),
                "found_date": obj.get("FoundDate"),
                "type": dict_safe_get(obj, ["Details", "Type"]),
                "severity": XSOAR_SEVERITY[dict_safe_get(obj, ["Details", "Severity"])],
                "title": dict_safe_get(obj, ["Details", "Title"]),
                "description": dict_safe_get(obj, ["Details", "Description"]),
                "update_date": obj.get("UpdateDate"),
                "Source": {
                    "type": dict_safe_get(obj, ["Details", "Source", "Type"]),
                    "network_type": dict_safe_get(obj, ["Details", "Source", "NetworkType"]),
                    "email": "",
                    "url": dict_safe_get(obj, ["Details", "Source", "URL"]),
                    "date": dict_safe_get(obj, ["Details", "Source", "Date"]),
                },
                "related_iocs": obj.get("RelatedIocs"),
                "takedown_status": obj.get("TakedownStatus"),
                "Assets": [
                    {
                        "type": asset.get("Type"),
                        "value": asset.get("Value"),
                    }
                    for asset in obj.get("Assets", [])
                ],
                "related_threat_ids": obj.get("RelatedThreatIDs"),
                "Tags": [
                    {
                        "created_by": tag.get("CreatedBy"),
                        "name": tag.get("Name"),
                        "id": tag.get("_id"),
                    }
                    for tag in dict_safe_get(obj, ["Details", "Tags"], [])
                ],
                "is_closed": dict_safe_get(obj, ["Closed", "IsClosed"]),
                "sub_type": dict_safe_get(obj, ["Details", "SubType"]),
            }
        )

    def parse_incident(self, alert: dict) -> dict:
        """
        Parse alert to XSOAR Incident.
        Args:
            alert (dict): alert item.
        Returns:
            dict: XSOAR Incident.
        """
        incident = {
            "name": alert.get("id"),
            "occurred": alert.get("found_date"),
            "rawJSON": json.dumps(alert),
        }
        return incident

    def alert_activity_parser(self, obj: dict[str, Any]) -> dict[str, Any]:
        """
        Parse complete Alert activity response from the API to XSOAR outputs.

        Args:
            obj (dict[str, Any]): Alert activity response from the API.

        Returns:
            dict[str, Any]: XSOAR outputs.
        """
        return remove_empty_elements(
            {
                "rate": dict_safe_get(obj, ["AdditionalInformation", "Status", "Rate"]),
                "type": obj.get("Type"),
                "sub_types": obj.get("SubTypes"),
                "initiator": obj.get("Initiator"),
                "created_date": obj.get("CreatedDate"),
                "update_date": obj.get("UpdateDate"),
                "read_by": obj.get("ReadBy"),
                "id": obj.get("_id"),
                "tag_names": dict_safe_get(obj, ["AdditionalInformation", "TagNames"]),
                "tag_ids": dict_safe_get(obj, ["AdditionalInformation", "TagIDs"]),
                "Mail": {
                    "note_id": dict_safe_get(obj, ["AdditionalInformation", "Mail", "NoteId"]),
                    "question": dict_safe_get(obj, ["AdditionalInformation", "Mail", "Question"]),
                    "Replies": [
                        {
                            "email": reply.get("Email"),
                            "token": reply.get("Token"),
                            "date": reply.get("Date"),
                            "read_by": reply.get("ReadBy"),
                            "is_token_valid": reply.get("IsTokenValid"),
                        }
                        for reply in dict_safe_get(obj, ["AdditionalInformation", "Mail", "Replies"], [])
                    ],
                },
                "Messages": [
                    {
                        "initiator_id": dict_safe_get(msg, ["Initiator", "_id"]),
                        "initiator_is_support": dict_safe_get(msg, ["Initiator", "IsSupport"]),
                        "date": msg.get("Date"),
                        "content": msg.get("Content"),
                    }
                    for msg in dict_safe_get(obj, ["AdditionalInformation", "AskTheAnalyst", "Messages"], [])
                ],
            }
        )

    def ioc_get_parser(self, obj: dict[str, Any]) -> dict[str, Any]:
        """
        Parse IOC response from the API to XSOAR outputs.

        Args:
            obj (dict[str, Any]): IOC response from the API.

        Returns:
            dict[str, Any]: XSOAR outputs.
        """
        return {
            "value": obj.get("value"),
            "type": obj.get("type"),
            "status": obj.get("status"),
            "severity": obj.get("severity"),
            "score": obj.get("score"),
            "last_update_date": obj.get("lastUpdateDate"),
            "last_seen": obj.get("lastSeen"),
            "first_seen": obj.get("firstSeen"),
            "related_malware": obj.get("relatedMalware"),
            "related_campaigns": obj.get("relatedCampaigns"),
            "related_threat_actors": obj.get("relatedThreatActors"),
            "ReportedFeeds": [
                {
                    "id": feed.get("id"),
                    "name": feed.get("name"),
                    "confidence_level": feed.get("confidenceLevel"),
                }
                for feed in obj.get("reportedFeeds", [])
            ],
            "is_whitelisted": obj.get("whitelisted"),
            "tags": obj.get("tags"),
        }

    def ioc_enrich_parser(self, obj: dict[str, Any]) -> dict[str, Any]:
        """
        Parse IOC enrich response from the API to XSOAR outputs.

        Args:
            obj (dict[str, Any]): IOC enrich response from the API.

        Returns:
            dict[str, Any]: XSOAR outputs.
        """
        return remove_empty_elements(
            {
                "value": obj.get("Value"),
                "type": obj.get("Type"),
                "Sources": [
                    {
                        "name": source.get("Name"),
                        "confidence_level": source.get("ConfidenceLevel"),
                    }
                    for source in obj.get("Sources", [])
                ],
                "system_tags": obj.get("SystemTags"),
                "tags": obj.get("Tags"),
                "status": obj.get("Status"),
                "is_known_ioc": obj.get("IsKnownIoc"),
                "related_threat_actors": obj.get("RelatedThreatActors"),
                "related_campaign": obj.get("RelatedCampaigns"),
                "first_seen": obj.get("FirstSeen"),
                "last_seen": obj.get("LastSeen"),
                "update_seen": obj.get("UpdateDate"),
                "is_whitelisted": obj.get("Whitelisted"),
                "Severity": {
                    "value": dict_safe_get(obj, ["Severity", "Value"]),
                    "score": dict_safe_get(obj, ["Severity", "Score"]),
                    "origin": dict_safe_get(obj, ["Severity", "Origin"]),
                },
                "DnsRecord": [
                    {
                        "value": record.get("Value"),
                        "type": record.get("Type"),
                        "first_resolved": record.get("FirstResolved"),
                        "last_resolved": record.get("LastResolved"),
                        "count": record.get("Count"),
                    }
                    for record in obj.get("DnsRecords", [])
                ],
                "subdomains": obj.get("Subdomains"),
                "History": [
                    {
                        "status": source.get("Statuses"),
                        "name_servers": source.get("NameServers"),
                    }
                    for source in dict_safe_get(obj, ["Whois", "History"], [])
                ],
                "Current": {
                    "status": dict_safe_get(obj, ["Whois", "Current", "Statuses"]),
                    "name_servers": dict_safe_get(obj, ["Whois", "Current", "NameServers"]),
                },
                "Resolution": [
                    {
                        "resolved_ip_address": res.get("ResolvedIpAddress"),
                        "resolved_domain": res.get("ResolvedDomain"),
                        "reporting_sources": res.get("ReportingSources"),
                    }
                    for res in obj.get("Resolutions", [])
                ],
                "RelatedHash": {
                    "downloaded": dict_safe_get(obj, ["RelatedHashes", "downloaded"]),
                    "communicating": dict_safe_get(obj, ["RelatedHashes", "communicating"]),
                    "referencing": dict_safe_get(obj, ["RelatedHashes", "referencing"]),
                    "Hashes": [
                        {
                            "type": res.get("Type"),
                            "value": res.get("Value"),
                        }
                        for res in obj["RelatedHashes"]
                    ]
                    if isinstance(obj["RelatedHashes"], list)
                    else None,
                },
                "antivirus_scan_date": obj.get("AntivirusScanDate"),
                "file_name": obj.get("FileName"),
                "file_type": obj.get("FileType"),
                "file_author": obj.get("FileAuthor"),
                "file_description": obj.get("FileDescription"),
                "file_size": obj.get("FileSize"),
                "antivirus_detection_ratio": obj.get("AntivirusDetectionRatio"),
                "antivirus_detected_engines": obj.get("AntivirusDetectedEngines"),
                "ip_range": dict_safe_get(obj, ["Whois", "NetworkDetails", "IPRange"]),
                "AntivirusDetection": [
                    {
                        "name": res.get("Name"),
                        "version": res.get("Version"),
                        "detected": res.get("Detected"),
                        "result": res.get("Result"),
                    }
                    for res in obj.get("AntivirusDetections", [])
                ],
            }
        )

    def mention_parser(self, obj: dict[str, Any]) -> dict[str, Any]:
        """
        Parse mention response from the API to XSOAR outputs.

        Args:
            obj (dict[str, Any]): Mention response from the API.

        Returns:
            dict[str, Any]: XSOAR outputs.
        """
        return remove_empty_elements(
            {
                "author": obj.get("Author"),
                "comment_number": obj.get("CommentNumber"),
                "original_url": obj.get("OriginalUrl"),
                "source_date": obj.get("SourceDate"),
                "url": obj.get("Url"),
                "insertion_date": obj.get("InsertionDate"),
                "type": obj.get("Type"),
                "Tags": obj.get("Tags"),
                "id": obj.get("id"),
                "short_content": obj.get("ShortContent"),
                "title": obj.get("Title"),
                "date": obj.get("Date"),
            }
        )

    def file_reputation_parser(self, obj: dict[str, Any], reliability, hash_) -> dict[str, Any]:
        """
        Parse hash enrichment response from the API to XSOAR outputs.

        Args:
            obj (dict[str, Any]): Hash enrichment response from the API.
            reliability (_type_): Reliability of the source providing the intelligence data.
            hash_ (bool): Hash value.

        Returns:
            dict[str, Any]: XSOAR outputs.
        """
        related_hashes = get_enrich_hashes(obj)
        is_known_ioc = dict_safe_get(obj, ["Data", "IsKnownIoc"])
        dbot_score = get_dbotscore(reliability, hash_, is_known_ioc)
        tags = dict_safe_get(obj, ["Data", "Tags"], []) + dict_safe_get(obj, ["Data", "SystemTags"], [])
        return remove_empty_elements(
            {
                "md5": related_hashes.get("md5"),
                "sha1": related_hashes.get("SHA1"),
                "sha256": related_hashes.get("SHA256"),
                "sha512": related_hashes.get("SHA512"),
                "name": dict_safe_get(obj, ["Data", "FileName"]),
                "description": dict_safe_get(obj, ["Data", "FileDescription"]),
                "size": dict_safe_get(obj, ["Data", "FileSize"]),
                "file_type": dict_safe_get(obj, ["Data", "FileType"]),
                "tags": tags,
                "actor": dict_safe_get(obj, ["Data", "RelatedThreatActors"]),
                "campaign": dict_safe_get(obj, ["Data", "RelatedCampaigns"]),
                "associated_file_names": get_enrich_file_nams(obj),
                "dbot_score": dbot_score,
            }
        )

    def ip_reputation_parser(self, obj: dict[str, Any], reliability, ip) -> dict[str, Any]:
        """
        Parse IP enrichment response from the API to XSOAR outputs.

        Args:
            obj (dict[str, Any]): IP enrichment response from the API.
            reliability (_type_): Reliability of the source providing the intelligence data.
            ip (bool): IP value.

        Returns:
            dict[str, Any]: XSOAR outputs.
        """
        is_known_ioc = dict_safe_get(obj, ["Data", "IsKnownIoc"])
        dbot_score = get_dbotscore(reliability, ip, is_known_ioc)
        tags = dict_safe_get(obj, ["Data", "Tags"], []) + dict_safe_get(obj, ["Data", "SystemTags"], [])
        return remove_empty_elements(
            {
                "ip": ip,
                "asn": dict_safe_get(obj, ["Data", "IpDetails", "ASN"]),
                "region": dict_safe_get(obj, ["Data", "IpDetails", "Country"]),
                "updated_date": dict_safe_get(obj, ["Data", "UpdateDate"]),
                "campaign": dict_safe_get(obj, ["Data", "RelatedCampaigns"]),
                "tags": tags,
                # "whois_records": dict_safe_get(
                #     obj, ["Data", "Whois", "RegistrantDetails"]
                # ),
                "dbot_score": dbot_score,
            }
        )

    def url_reputation_parser(self, obj: dict[str, Any], reliability, url) -> dict[str, Any]:
        """
        Parse url enrichment response from the API to XSOAR outputs.

        Args:
            obj (dict[str, Any]): Url enrichment response from the API.
            reliability (_type_): Reliability of the source providing the intelligence data.
            url (bool): url value.

        Returns:
            dict[str, Any]: XSOAR outputs.
        """
        is_known_ioc = dict_safe_get(obj, ["Data", "IsKnownIoc"])
        dbot_score = get_dbotscore(reliability, url, is_known_ioc)
        antivirus_detected_engines: str = dict_safe_get(obj, ["Data", "AntivirusDetectedEngines"])
        if len(antivirus_detected_engines.split("/")) == 2:
            detection_engines = antivirus_detected_engines.split("/")[1]
            positive_detections = antivirus_detected_engines.split("/")[0]
        else:
            detection_engines = None
            positive_detections = None

        tags = dict_safe_get(obj, ["Data", "Tags"], []) + dict_safe_get(obj, ["Data", "SystemTags"], [])
        return remove_empty_elements(
            {
                "url": url,
                "detection_engines": detection_engines,
                "positive_detections": positive_detections,
                "campaign": dict_safe_get(obj, ["Data", "RelatedCampaigns"]),
                "tags": tags,
                "dbot_score": dbot_score,
            }
        )

    def domain_reputation_parser(self, obj: dict[str, Any], reliability, domain) -> dict[str, Any]:
        """
        Parse domain enrichment response from the API to XSOAR outputs.

        Args:
            obj (dict[str, Any]): Domain enrichment response from the API.
            reliability (_type_): Reliability of the source providing the intelligence data.
            domain (bool): domain value.

        Returns:
            dict[str, Any]: XSOAR outputs.
        """
        is_known_ioc = dict_safe_get(obj, ["Data", "IsKnownIoc"])
        dbot_score = get_dbotscore(reliability, domain, is_known_ioc)
        tags = dict_safe_get(obj, ["Data", "Tags"], []) + dict_safe_get(obj, ["Data", "SystemTags"], [])
        dns_records: List[Common.DNSRecord] = []
        for dns in dict_safe_get(obj, ["Data", "DnsRecords"], []):
            dns_records.append(Common.DNSRecord(dns_record_type=dns["Type"], dns_record_data=dns["Value"]))
        return remove_empty_elements(
            {
                "domain": domain,
                # "whois_records": dict_safe_get(obj, ["Data", "Whois"]),
                "dns_records": dns_records,
                "updated_date": dict_safe_get(obj, ["Data", "UpdateDate"]),
                "tags": tags,
                "sub_domains": dict_safe_get(obj, ["Data", "Subdomains"]),
                "campaign": dict_safe_get(obj, ["Data", "RelatedCampaigns"]),
                "dbot_score": dbot_score,
            }
        )
        # ) | {"dns_records": dns_records}


class Client(BaseClient):
    """Client class to interact with Threat Command API."""

    def __init__(
        self,
        base_url: str,
        account_id: str,
        api_key: str,
        mssp_sub_account: str | None,
        reliability: str,
        verify: bool,
        proxy: bool,
    ):
        self.reliability = reliability
        base_url = urljoin(base_url, "public")
        self.parser = Parser()
        super().__init__(
            base_url=base_url,
            headers=remove_empty_elements({"Account-Id": mssp_sub_account}),
            verify=verify,
            proxy=proxy,
            auth=(account_id, api_key),
        )

    def _http_request(self, *args, **kwargs):
        """
        Warp to _http_request command. I use it because sometimes the API response code is 200
        but there is an error with the request. The error flag located in the response body.

        Raises:
            DemistoException: Error response.
            DemistoException: Error response.

        Returns:
            Response | dict[str,Any]: API response from Threat Command API.
        """
        kwargs["error_handler"] = self.error_handler
        demisto.debug(
            f'Making API request at {kwargs.get("method")} {kwargs.get("url_suffix")} '
            f'with params:{kwargs.get("params")} and body:{kwargs.get("json_data")}'
        )
        res = super()._http_request(
            backoff_factor=BACKOFF_FACTOR,
            retries=RETRIES,  # type: ignore
            status_list_to_retry=STATUS_LIST_TO_RETRY,
            raise_on_status=True,  # type: ignore
            *args,
            **kwargs,
        )  # type: ignore
        if isinstance(res, dict):
            if res.get("Success") is False and (data := res.get("Data")) and ERROR_RESPONSE_MAPPER.get(data):
                raise DemistoException(message=ERROR_RESPONSE_MAPPER.get(data))
            if dict_safe_get(res, ["content", "success"]) is False:
                raise DemistoException(message=res)
        return res

    def error_handler(self, res: Response):
        """
        Handling with request errors.

        Args:
            res (Response): API response from Threat Command API.

        Raises:
            DemistoException: Error response.
            DemistoException: Error response.
            DemistoException: Error response.
            DemistoException: Error response.
        """
        error_str = f"Status Code: {res.status_code}, Message: {res.text}"
        if isinstance(res, Response):
            if ERROR_RESPONSE_MAPPER.get(res.content.decode()):
                raise DemistoException(ERROR_RESPONSE_MAPPER.get(res.content.decode()))
            if ERROR_CODE_MAPPER.get(res.status_code):
                raise DemistoException(f"Status Code: {res.status_code}, {ERROR_CODE_MAPPER.get(res.status_code)}")
        raise DemistoException(message=error_str)

    def list_cyber_term_cve(self, cyber_term_id: str) -> dict[str, Any]:
        """
        List the Cyber-term CVEs.

        Args:
            cyber_term_id (str): The ID of the cyber-term.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.CYBER_TERM}/{cyber_term_id}/cves"
        return self._http_request(method="GET", url_suffix=url_suffix)

    def list_cyber_term_ioc(
        self,
        cyber_term_id: str,
        limit: int,
        ioc_type: str | None,
        offset: str | None,
    ) -> dict[str, Any]:
        """
        List the Cyber-term IOCs.

        Args:
            cyber_term_id (str | None): The ID of the cyber-term.
            limit (int): The maximum number of records to retrieve.
            ioc_type (str | None): IOC type to filter.
            offset (str | None): Offset for pagination.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """

        params = remove_empty_elements(
            {
                "iocType": remove_whitespaces(ioc_type),
                "limit": limit,
                "offset": offset,
            }
        )
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.CYBER_TERM}/{cyber_term_id}/iocs"
        return self._http_request(method="GET", url_suffix=url_suffix, params=params)

    def list_cyber_term(
        self,
        search: str | None,
        types_: List[str] | None,
        severities: List[str] | None,
        sectors: List[str] | None,
        countries: List[str] | None,
        origin: List[str] | None,
        ttp: List[str] | None,
        last_update_from: str | None,
        last_update_to: str | None,
        limit: int,
        offset: str | None,
    ) -> dict[str, Any]:
        """List Cyber terms.

        Args:
            search (str | None): Filter by free text, which can be the cyber term name or ID.
            types_ (str | None): Filter by one or more cyber term types.
            severities (str | None): Filter by one or more cyber term severities.
            sectors (List[str] | None): Filter by one or more targeted sectors.
            countries (List[str] | None): Filter by one or more targeted countries.
            origin (List[str] | None): Filter by one or more nationalities.
            ttp (List[str] | None): Filter by one or more TTPs.
            last_update_from (str | None): Filter by last update date is greater than (in ISO 8601 format).
            last_update_to (str | None): Filter by last update date is less than (in ISO 8601 format).
            limit (int): The maximum number of records to retrieve.
            offset (str | None): Offset for pagination.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        params = remove_empty_elements(
            {
                "search": search,
                "type": [remove_whitespaces(type_) for type_ in types_] if types_ else None,
                "severity": severities,
                "target-sector": sectors,
                "target-country": countries,
                "origin": origin,
                "ttp": ttp,
                "last-update-from": last_update_from,
                "last-update-to": last_update_to,
                "limit": limit,
                "offset": offset,
            }
        )
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.CYBER_TERM}"
        return self._http_request(method="GET", url_suffix=url_suffix, params=params)

    def list_source(self) -> dict[str, Any]:
        """
        List the IOC sources.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.IOC_SOURCE}/sources"
        return self._http_request(method="GET", url_suffix=url_suffix)

    def create_document_source(
        self,
        name: str,
        description: str,
        confidence_level: int,
        share: bool | None,
        severity: str | None,
        tags: List[str],
        domains: List[str],
        urls: List[str],
        ips: List[str],
        hashes: List[str],
        emails: List[str],
    ) -> dict[str, Any]:
        """
        Create document source.

        Args:
            name (str): Source name.
            description (str): Source description.
            confidence_level (int): Source confidence level.
            share (bool | None): Share this source with all tenants (available for MSSP users only).
            severity (str | None): Source severity level.
            tags (List[str]): A list of user tags for the document.
            domains (List[str]): A list of domain IOC values to add.
            urls (str): A list of URL IOC values to add.
            ips (List[str]): A list of IP IOC values to add.
            hashes (List[str]): A list hash domain IOC values to add.
            emails (List[str]): A list of email IOC values to add.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        payload = remove_empty_elements(
            {
                "DocumentDetails": {
                    "Name": name,
                    "Description": description,
                    "ConfidenceLevel": confidence_level,
                    "Share": share,
                    "Severity": severity.lower() if severity else None,
                    "Tags": tags,
                },
                "Iocs": map_ioc_list(domains=domains, urls=urls, ips=ips, hashes=hashes, emails=emails),
            }
        )
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.IOC_SOURCE}/add-source"
        return self._http_request(
            method="POST",
            url_suffix=url_suffix,
            json_data=payload,
        )

    def delete_document_source(self, source_id: str) -> Response:
        """
        Delete document source.

        Args:
            source_id (str): The ID of the document source.

        Returns:
            Response: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.IOC_SOURCE}/delete-source/{source_id}"
        return self._http_request(
            method="DELETE",
            url_suffix=url_suffix,
            ok_codes=[HTTPStatus.OK],
            resp_type="response",
        )

    def create_document_source_ioc(
        self,
        source_id: str,
        domains: List[str],
        urls: List[str],
        ips: List[str],
        hashes: List[str],
        emails: List[str],
    ) -> Response:
        """
        Create new IOCs to existing IOC source documents.

        Args:
            source_id (str): The ID of the document source.
            domains (List[str]): A list of domain IOC values to add.
            urls (str): A list of URL IOC values to add.
            ips (List[str]): A list of IP IOC values to add.
            hashes (List[str]): A list hash domain IOC values to add.
            emails (List[str]): A list of email IOC values to add.

        Returns:
            Response: API response from Threat Command API.
        """
        payload = remove_empty_elements(
            {
                "Iocs": map_ioc_list(
                    domains=domains,
                    urls=urls,
                    ips=ips,
                    hashes=hashes,
                    emails=emails,
                )
            }
        )
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.IOC_SOURCE}/add-iocs-to-source/{source_id}"
        return self._http_request(
            method="POST",
            url_suffix=url_suffix,
            json_data=payload,
            ok_codes=[HTTPStatus.OK],
            resp_type="response",
        )

    def list_system_modules(self) -> dict[str, Any]:
        """
        List the system modules.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ACCOUNT}/system-modules"
        return self._http_request(method="GET", url_suffix=url_suffix)

    def add_asset(self, asset_type: str, asset_value: str) -> Response:
        """
        Add a new asset to asset list.

        Args:
            asset_type (str): The type of the asset.
            asset_value (str): The asset value.

        Returns:
            Response: API response from Threat Command API.
        """
        payload = {"AssetType": asset_type, "AssetValue": asset_value}
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ASSET}/add-asset"
        return self._http_request(
            method="PUT",
            url_suffix=url_suffix,
            ok_codes=[HTTPStatus.OK],
            json_data=payload,
            resp_type="response",
        )

    def delete_asset(self, asset_type: str, asset_value: str) -> Response:
        """
        Delete an asset to asset list.

        Args:
            asset_type (str): The type of the asset.
            asset_value (str): The asset value.

        Returns:
            Response: API response from Threat Command API.
        """
        payload = {"AssetType": asset_type, "AssetValue": asset_value}
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ASSET}/delete-asset"
        return self._http_request(
            method="DELETE",
            url_suffix=url_suffix,
            ok_codes=[HTTPStatus.OK],
            json_data=payload,
            resp_type="response",
        )

    def list_assets(self, asset_types: List[str] | None) -> dict[str, Any]:
        """
        List assets.

        Args:
            asset_types (List[str] | None): Type for filter.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        params = remove_empty_elements({"assetTypes": asset_types if asset_types else None})
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ASSET}/account-assets"
        return self._http_request(method="GET", url_suffix=url_suffix, ok_codes=[HTTPStatus.OK], params=params)

    def list_asset_types(self) -> List[str]:
        """
        List asset types.

        Returns:
            List[str]: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ASSET}/assets-types"
        return self._http_request(method="GET", url_suffix=url_suffix, ok_codes=[HTTPStatus.OK])

    def list_cve(
        self,
        offset: str | None,
        publish_date_from: str | None,
        publish_date_to: str | None,
        update_date_from: str | None,
        update_date_to: str | None,
        severity_list: List[str] | None,
        cpe_list: List[str] | None,
        cve_ids: List[str] | None,
    ) -> dict[str, Any]:
        """
        List of CVEs.

        Args:
            offset (str | None): Offset for pagination.
            publish_date_from (str | None): Publish date from.
            publish_date_to (str | None): Publish date to.
            update_date_from (str | None): Update date from.
            update_date_to (str | None): Update date to.
            severity_list (List[str] | None): Severity list.
            cpe_list (List[str] | None): CPE list.
            cve_ids (List[str] | None): CVE IDs.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        params = remove_empty_elements(
            {
                "publishDateFrom": publish_date_from,
                "publishDateTo": publish_date_to,
                "updateDateFrom": update_date_from,
                "updateDateTo": update_date_to,
                "severity": severity_list if severity_list else None,
                "cpe": cpe_list if cpe_list else None,
                "cveId": cve_ids if cve_ids else None,
                "offset": offset,
            }
        )
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.CVE}/get-cves-list"
        return self._http_request(method="GET", url_suffix=url_suffix, params=params)

    def add_cve(self, cve_ids: List[str]) -> dict[str, Any]:
        """
        Add CVEs to account.

        Args:
            cve_ids (List[str]): List of CVE IDs to add.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        payload = {"cveIds": cve_ids}
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.CVE}/add-cves"
        return self._http_request(
            method="POST",
            url_suffix=url_suffix,
            ok_codes=[HTTPStatus.OK],
            json_data=payload,
        )

    def delete_cve(self, cve_ids: List[str]) -> dict[str, Any]:
        """
        Delete CVEs from account.

        Args:
            cve_ids (List[str]): List of CVE IDs to delete.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        payload = {"cveIds": cve_ids}
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.CVE}/delete-cves"
        return self._http_request(
            method="DELETE",
            url_suffix=url_suffix,
            ok_codes=[HTTPStatus.OK],
            json_data=payload,
        )

    def list_alert(
        self,
        limit: int,
        is_closed: bool,
        offset: str | None = None,
        last_updated_from: str | None = None,
        last_updated_to: str | None = None,
        alert_type: List[str] | None = None,
        severity: List[str] | None = None,
        source_type: List[str] | None = None,
        network_type: List[str] | None = None,
        matched_asset_value: List[str] | None = None,
        source_date_from: str | None = None,
        source_date_to: str | None = None,
        found_date_from: str | None = None,
        found_date_to: str | None = None,
        assigned: bool | None = None,
        is_flagged: bool | None = None,
        has_ioc: bool | None = None,
    ) -> dict[str, Any]:
        """
        List alerts with updated date.

        Args:
            limit (int): Limit for pagination.
            is_closed (bool): Whether the alert is closed.
            offset (str | None): Offset for pagination.
            last_updated_from (str | None): Last updated from date for filter.
            last_updated_to (str | None): Last updated to date for filter.
            alert_type (List[str] | None): Alert types for filter.
            severity (List[str] | None): Alert severities for filter.
            source_type (List[str] | None): Alert source types for filter.
            network_type (List[str] | None): Alert network types for filter.
            matched_asset_value (List[str] | None): Alert matched asset values for filter.
            source_date_from (str | None): Source date from for filter.
            source_date_to (str | None): Source date to for filter.
            found_date_from (str | None): Found date from for filter.
            found_date_to (str | None): Found date from for filter.
            assigned (bool | None): Assigned user for filter.
            is_flagged (bool | None): Whether the alert is flagged.
            has_ioc (bool | None): Whether the alert has IOCs.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        params = remove_empty_elements(
            {
                "lastUpdatedFrom": last_updated_from,
                "lastUpdatedTo": last_updated_to,
                "alertType": [remove_whitespaces(_type) for _type in alert_type] if alert_type else None,
                "severity": severity if severity else None,
                "sourceType": [remove_whitespaces(_type) for _type in source_type] if source_type else None,
                "networkType": [remove_whitespaces(_type) for _type in network_type] if network_type else None,
                "matchedAssetValue": matched_asset_value if matched_asset_value else None,
                "sourceDateFrom": source_date_from,
                "sourceDateTo": source_date_to,
                "foundDateFrom": found_date_from,
                "foundDateTo": found_date_to,
                "assigned": str(assigned).lower() if assigned else None,
                "isFlagged": str(is_flagged).lower() if is_flagged else None,
                "isClosed": str(is_closed).lower() if is_closed else None,
                "hasIoc": str(has_ioc).lower() if has_ioc else None,
                "limit": limit,
                "offset": offset,
            }
        )
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/update-alerts"
        return self._http_request(method="GET", url_suffix=url_suffix, params=params, ok_codes=[HTTPStatus.OK])

    def get_alert(self, alert_id: str) -> dict[str, Any]:
        """
        Get alert with complete details.

        Args:
            alert_id (str): Alert ID.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/get-complete-alert/{alert_id}"
        return self._http_request(method="GET", url_suffix=url_suffix, ok_codes=[HTTPStatus.OK])

    def create_alert(
        self,
        title: str,
        description: str,
        type_: str | None,
        sub_type: str | None,
        severity: str,
        source_type: str,
        source_network_type: str,
        source_date: str | None,
        found_date: str | None,
        image_entry_ids: List[str],
        scenario: str | None,
        source_url: str | None,
    ) -> Response:
        """
        Create a new alert.

        Args:
            title (str): Title for the alert.
            description (str): Description for the alert.
            type_ (str | None): Type for the alert.
            sub_type (str | None): Sub-type for the alert.
            severity (str): Severity.
            source_type (str): Source type.
            source_network_type (str): Source network.
            source_date (str | None): Source date.
            found_date (str | None): Found date.
            image_entry_ids (List[str]]): Images data.
            scenario (str | None): Scenario.
            source_url (str | None): Source URL.

        Returns:
            Response: API response from Threat Command API.
        """
        payload = remove_empty_elements(
            {
                "FoundDate": found_date,
                "Details": {
                    "Title": title,
                    "Description": description,
                    "Type": remove_whitespaces(type_),
                    "SubType": sub_type,
                    "Severity": severity,
                    "Source": {
                        "Type": source_type,
                        "NetworkType": remove_whitespaces(source_network_type),
                        "URL": source_url,
                        "Date": source_date if source_date else "",
                    },
                    "Images": files_handler(file_ids=image_entry_ids, is_image=True),
                },
                "Scenario": scenario,
            }
        )
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/add-alert"

        return self._http_request(
            method="PUT",
            url_suffix=url_suffix,
            ok_codes=[HTTPStatus.OK],
            json_data=payload,
            resp_type="response",
        )

    def close_alert(
        self,
        alert_id: str,
        reason: str,
        comment: str | None,
        is_hidden: bool,
        rate: int | None,
    ) -> Response:
        """
        Close alert.

        Args:
            alert_id (str): Alert ID.
            reason (str): Close reason.
            comment (str | None): Close comment.
            is_hidden (bool): Alerts' hidden status.
            rate (int | None): Alert's rate

        Returns:
            Response: API response from Threat Command API.
        """
        payload = remove_empty_elements(
            {
                "Reason": remove_whitespaces(reason),
                "FreeText": comment,
                "IsHidden": is_hidden,
                "Rate": rate,
            }
        )
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/close-alert/{alert_id}"
        return self._http_request(
            method="PATCH",
            url_suffix=url_suffix,
            json_data=payload,
            resp_type="response",
        )

    def update_alert_severity(self, alert_id: str, severity: str) -> Response:
        """
        Update alert severity.

        Args:
            alert_id (str): Alert ID.
            severity (str): Alert severity.

        Returns:
            Response: API response from Threat Command API.
        """
        payload = {"Severity": severity}
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/change-severity/{alert_id}"
        return self._http_request(
            method="PATCH",
            url_suffix=url_suffix,
            json_data=payload,
            resp_type="response",
        )

    def assign_alert(self, alert_id: str, user_id: str, is_mssp: bool) -> Response:
        """
        Assign alert to user.

        Args:
            alert_id (str): Alert ID.
            user_id (str): User ID.
            is_mssp (bool): Whether to user is MSSP.

        Returns:
            Response: API response from Threat Command API.
        """
        payload = {
            "AssigneeID": user_id,
            "IsMssp": is_mssp,
        }
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/assign-alert/{alert_id}"
        return self._http_request(
            method="PATCH",
            url_suffix=url_suffix,
            json_data=payload,
            resp_type="response",
        )

    def unassign_alert(self, alert_id: str) -> Response:
        """
        Unassign alert.

        Args:
            alert_id (str): Alert ID.

        Returns:
            Response: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/unassign-alert/{alert_id}"
        return self._http_request(method="PATCH", url_suffix=url_suffix, resp_type="response")

    def reopen_alert(self, alert_id: str) -> Response:
        """
        Re-open alert.

        Args:
            alert_id (str): Alert ID.

        Returns:
            Response: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/reopen-alert/{alert_id}"
        return self._http_request(method="PATCH", url_suffix=url_suffix, resp_type="response")

    def tag_alert(self, alert_id: str, tag_name: str) -> Response:
        """
        Add a tag to alert.

        Args:
            alert_id (str): Alert ID.
            tag_name (str): Tag to add.

        Returns:
            Response: API response from Threat Command API.
        """
        payload = {
            "TagName": tag_name,
        }
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/add-tag/{alert_id}"
        return self._http_request(
            method="PATCH",
            url_suffix=url_suffix,
            json_data=payload,
            resp_type="response",
        )

    def untag_alert(self, alert_id: str, tag_id: str) -> Response:
        """
        Remove a tag to alert.

        Args:
            alert_id (str): Alert ID.
            tag_id (str): Tag ID to remove.

        Returns:
            Response: API response from Threat Command API.
        """
        payload = {
            "TagID": tag_id,
        }
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/remove-tag/{alert_id}"
        return self._http_request(
            method="PATCH",
            url_suffix=url_suffix,
            json_data=payload,
            resp_type="response",
        )

    def send_mail_alert(self, alert_id: str, email_addresses: List[str], content: str) -> Response:
        """
        Send mail with the alert details and a question.


        Args:
            alert_id (str): Alert ID.
            email_addresses (List[str]): List of mails to send.
            content (str): Content.

        Returns:
            Response: API response from Threat Command API.
        """
        payload = {"Emails": email_addresses, "Content": content}
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/send-mail/{alert_id}"
        return self._http_request(
            method="POST",
            url_suffix=url_suffix,
            json_data=payload,
            resp_type="response",
        )

    def analyst_ask_alert(self, alert_id: str, question: str) -> Response:
        """
        Send a question to an analyst about the requested alert.

        Args:
            alert_id (str): Alert ID.
            question (str): Question to ask.

        Returns:
            Response: API response from Threat Command API.
        """
        payload = {"Question": question}
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/ask-the-analyst/{alert_id}"
        return self._http_request(
            method="POST",
            url_suffix=url_suffix,
            json_data=payload,
            resp_type="response",
        )

    def list_alert_conversation(self, alert_id: str) -> Response:
        """
        List alert's analyst response.

        Args:
            alert_id (str): Alert ID.

        Returns:
            Response: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/ask-the-analyst-conversation/{alert_id}"
        return self._http_request(
            method="GET",
            url_suffix=url_suffix,
            ok_codes=[HTTPStatus.OK, HTTPStatus.NO_CONTENT],
            resp_type="response",
        )

    def list_alert_activity(self, alert_id: str) -> List[dict[str, Any]]:
        """
        Get alert activity log.

        Args:
            alert_id (str): Alert ID.

        Returns:
            List[dict[str, Any]]: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/activity-log/{alert_id}"
        return self._http_request(method="GET", url_suffix=url_suffix)

    def add_alert_note(self, alert_id: str, note: str, file_entry_ids: List[str]) -> Response:
        """
        Add note to alert.

        Args:
            alert_id (str): Alert ID.
            note (str): Note text to add.
            file_entry_ids (List[str]): File entry ids.

        Returns:
            Response: API response from Threat Command API.
        """
        payload = {"Note": note, "Files": files_handler(file_ids=file_entry_ids)}
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/add-note/{alert_id}"
        return self._http_request(
            method="POST",
            url_suffix=url_suffix,
            json_data=payload,
            resp_type="response",
        )

    def get_alert_blocklist(self, alert_id: str) -> List[dict[str, Any]]:
        """
        Get alert blocklist.

        Args:
            alert_id (str): Alert ID.

        Returns:
            List[dict[str, Any]]: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/blocklist-status/{alert_id}"
        return self._http_request(method="GET", url_suffix=url_suffix)

    def update_alert_blocklist(
        self,
        alert_id: str,
        domains: List[str],
        urls: List[str],
        ips: List[str],
        emails: List[str],
        blocklist_status: str,
    ) -> Response:
        """
        Update alert blocklist.

        Args:
            alert_id (str): Alert ID.
            domains (List[str]): Domains IOCs.
            urls (List[str]): URL IOCs.
            ips (List[str]): IP IOCs.
            emails (List[str]): Email IOCs.
            blocklist_status (str): Blocklist status.

        Returns:
            Response: API response from Threat Command API.
        """
        payload = remove_empty_elements(
            {
                "Iocs": map_ioc_list(
                    domains=domains,
                    urls=urls,
                    ips=ips,
                    emails=emails,
                    blocklist_status=remove_whitespaces(blocklist_status),
                )
            }
        )
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/change-iocs-blocklist-status/{alert_id}"
        return self._http_request(
            method="PATCH",
            url_suffix=url_suffix,
            json_data=payload,
            ok_codes=[HTTPStatus.OK],
            resp_type="response",
        )

    def get_alert_image(self, image_id: str) -> Response:
        """
        Get alert image.

        Args:
            image_id (str): Image ID.

        Returns:
            Response: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/alert-image/{image_id}"
        return self._http_request(method="GET", url_suffix=url_suffix, resp_type="response")

    def takedown_alert(self, alert_id: str, target: str, close_alert_after_success: bool) -> Response:
        """
        Takedown alert.

        Args:
            alert_id (str): Alert ID.
            target (str): Target.
            close_alert_after_success (bool): Whether to close after success.

        Returns:
            Response: API response from Threat Command API.
        """
        payload = {
            "Target": target,
            "ShouldCloseAlertAfterSuccess": close_alert_after_success,
        }
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/takedown-request/{alert_id}"
        return self._http_request(
            method="PATCH",
            url_suffix=url_suffix,
            json_data=payload,
            resp_type="response",
        )

    def get_takedown_alert(self, alert_id: str) -> Response:
        """
        Get takedown status.

        Args:
            alert_id (str): Alert ID.

        Returns:
            Response: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/takedown-status/{alert_id}"
        return self._http_request(method="GET", url_suffix=url_suffix, resp_type="response")

    def list_alert_type(self) -> dict[str, Any]:
        """
        List alert types.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/types-subtypes-relations"
        return self._http_request(method="GET", url_suffix=url_suffix)

    def list_alert_source_type(self) -> List[dict[str, Any]]:
        """
        List alert sub-types.

        Returns:
            List[dict[str, Any]]: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/source-types"
        return self._http_request(method="GET", url_suffix=url_suffix)

    def list_alert_scenario(self, type_: str | None, sub_type: str | None) -> List[dict[str, Any]]:
        """
        List alert scenarios.

        Args:
            type_ (str | None): Filter by type.
            sub_type (str | None): Filter by sub-type.

        Returns:
            List[dict[str, Any]]: API response from Threat Command API.
        """
        params = remove_empty_elements({"type": remove_whitespaces(type_), "subType": sub_type})
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/scenario-relations"
        return self._http_request(method="GET", url_suffix=url_suffix, params=params)

    def report_alert_ioc(self, alert_id: str, external_sources: List[str]) -> Response:
        """
        List alert scenarios.

        Args:
            alert_id (str): Alert ID.
            external_sources (List[str]): External sources to report.

        Returns:
            Response: API response from Threat Command API.
        """
        payload = {"ExternalSources": external_sources}
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/report-iocs/{alert_id}"
        return self._http_request(
            method="POST",
            url_suffix=url_suffix,
            json_data=payload,
            resp_type="response",
        )

    def list_account_user(self, user_type: str | None, user_email: str | None, user_id: str | None) -> List[dict[str, Any]]:
        """List account users.

        Args:
            user_type (str | None): User type for filter.
            user_email (str | None): User Emails for filter.
            user_id (str | None): User ID for filter.

        Returns:
            List[dict[str, Any]]: API response from Threat Command API.
        """
        params = remove_empty_elements(
            {
                "userType": user_type,
                "userEmail": user_email,
                "userId": user_id,
            }
        )
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ACCOUNT}/users-details"
        return self._http_request(method="GET", url_suffix=url_suffix, params=params, ok_codes=[HTTPStatus.OK])

    def get_ioc(self, ioc_value: str) -> dict[str, Any]:
        """
        Get IOC.

        Args:
            ioc_value (str): IOC value.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        params = {
            "iocValue": ioc_value,
        }
        url_suffix = f"{V3_PREFIX}/{UrlPrefix.IOC}/ioc-by-value"
        return self._http_request(method="GET", url_suffix=url_suffix, params=params, ok_codes=[HTTPStatus.OK])

    def list_ioc(
        self,
        last_updated_from: str | None,
        last_updated_to: str | None,
        last_seen_from: str | None,
        last_seen_to: str | None,
        first_seen_from: str | None,
        first_seen_to: str | None,
        status: str | None,
        type_list: List[str] | None,
        severity_list: List[str] | None,
        whitelisted: bool | None,
        source_ids: List[str] | None,
        kill_chain_phases: List[str] | None,
        limit: str,
        offset: str | None,
    ) -> dict[str, Any]:
        """
        List IOCs.

        Args:
            last_updated_from (str | None): Last updated from filter.
            last_updated_to (str | None): Last updated to filter.
            last_seen_from (str | None): Last seen from filter.
            last_seen_to (str | None): Last seen to filter.
            first_seen_from (str | None): First seen from filter.
            first_seen_to (str | None): First seen to filter.
            status (str | None): Status filter.
            type_list (List[str] | None): List of types for filter.
            severity_list (List[str] | None): List of severities for filter.
            whitelisted (bool | None): Whitelist filter.
            source_ids (List[str] | None): List of source IDs for filter.
            kill_chain_phases (List[str] | None): List of phases for filter.
            limit (str): limit gor pagination.
            offset (str | None): Offset for pagination.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        params = remove_empty_elements(
            {
                "lastUpdatedFrom": last_updated_from,
                "lastUpdatedTo": last_updated_to,
                "lastSeenFrom": last_seen_from,
                "lastSeenTo": last_seen_to,
                "firstSeenFrom": first_seen_from,
                "firstSeenTo": first_seen_to,
                "status": status,
                "type": [remove_whitespaces(type) for type in type_list] if type_list else None,
                "severity": severity_list if severity_list else None,
                "whitelisted": whitelisted,
                "sourceIds": source_ids if source_ids else None,
                "killChainPhases": [remove_whitespaces(phase) for phase in kill_chain_phases] if kill_chain_phases else None,
                "limit": limit,
                "offset": offset,
            }
        )
        url_suffix = f"{V3_PREFIX}/{UrlPrefix.IOC}"
        return self._http_request(method="GET", url_suffix=url_suffix, params=params, ok_codes=[HTTPStatus.OK])

    def tags_ioc(self, ioc_value: str, tag_values: List[str]) -> dict[str, Any]:
        """
        Add tags for IOC.

        Args:
            ioc_value (str): IOC value.
            tag_values (List[str]): Tag to add.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        payload = [{"iocValue": ioc_value, "tag": tag} for tag in tag_values]
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.IOC}/tags"
        return self._http_request(
            method="POST",
            url_suffix=url_suffix,
            json_data=payload,
            ok_codes=[HTTPStatus.OK],
        )

    def update_ioc_severity(self, severity: str, ioc_values: List[str]) -> dict[str, Any]:
        """
        Update severity to IOCs.

        Args:
            severity (str): Severity to update.
            ioc_values (List[str]): IOC values.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        payload = [{"iocValue": ioc, "severity": severity} for ioc in ioc_values]
        url_suffix = f"{V2_PREFIX}/{UrlPrefix.IOC_SOURCE}/severity"
        return self._http_request(method="PATCH", url_suffix=url_suffix, json_data=payload)

    def add_ioc_comment(self, comment: str, ioc_values: List[str]) -> dict[str, Any]:
        """
        Add comment to IOCs.

        Args:
            comment (str): Comment to add.
            ioc_values (List[str]): IOC values.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        payload = [{"iocValue": ioc, "comment": comment} for ioc in ioc_values]
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.IOC_SOURCE}/comments"
        return self._http_request(method="POST", url_suffix=url_suffix, json_data=payload)

    def update_account_whitelist(self, is_whitelisted: str, ioc_values: List[str]) -> dict[str, Any]:
        """
        Update account whitelist.

        Args:
            is_whitelisted (str): IOC status.
            ioc_values (List[str]): List of IOCs.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """

        payload = {
            "iocs": [
                {
                    "value": ioc,
                    "whitelisted": ALERT_WHITELIST[is_whitelisted],
                }
                for ioc in ioc_values
            ]
        }
        url_suffix = f"{V2_PREFIX}/{UrlPrefix.IOC_SOURCE}/user-whitelist"
        return self._http_request(method="POST", url_suffix=url_suffix, json_data=payload)

    def remove_account_whitelist(self, ioc_values: List[str]) -> dict[str, Any]:
        """
        Remove IOCs from account whitelist.

        Args:
            ioc_values (List[str]): List of IOCs.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        payload = {"iocs": ioc_values}
        url_suffix = f"{V2_PREFIX}/{UrlPrefix.IOC_SOURCE}/user-whitelist"
        return self._http_request(method="DELETE", url_suffix=url_suffix, json_data=payload)

    def add_ioc_blocklist(self, ioc_values: List[str]) -> dict[str, Any]:
        """
        Add IOCs to remediation blocklist.

        Args:
            ioc_values (List[str]): List of IOCs.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        payload = {"iocs": ioc_values}
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.IOC_SOURCE}/blocklist"
        return self._http_request(method="POST", url_suffix=url_suffix, json_data=payload)

    def remove_ioc_blocklist(self, ioc_values: List[str]) -> dict[str, Any]:
        """
        Remove IOCs from remediation blocklist.

        Args:
            ioc_values (List[str]): List of IOCs.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        payload = {"iocs": ioc_values}
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.IOC_SOURCE}/blocklist"
        return self._http_request(method="DELETE", url_suffix=url_suffix, json_data=payload)

    def search_mention(
        self,
        search: str,
        report_date: str | None,
        page_number: int,
        source_types: str | None,
        only_dark_web: bool,
        highlight_tags: bool,
    ) -> dict[str, Any]:
        """
        Search for mentions.

        Args:
            search (str): Text for search.
            report_date (str | None): Report date
            page_number (int): Page number.
            source_types (str | None): Search source types.
            only_dark_web (bool): Show only mentions from the dark web or not.
            highlight_tags (bool): Show highlight tags (<em>) in the content or not.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """

        params = remove_empty_elements(
            {
                "search": search,
                "report-date": report_date,
                "page-number": page_number,
                "source-type": [remove_whitespaces(type_) for type_ in source_types] if source_types else None,
                "only-dark-web": only_dark_web,
                "highlight-tags": highlight_tags,
            }
        )
        url_suffix = f"{V2_PREFIX}/intellifind"
        return self._http_request(method="GET", url_suffix=url_suffix, params=params)

    def usage_quota_enrichment(self) -> dict[str, Any]:
        """
        Gets the current API enrichment credits.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.IOC}/quota"
        return self._http_request(method="GET", url_suffix=url_suffix)

    def enrich_ioc(self, ioc_value: str) -> dict[str, Any]:
        """
        Enrich IOC.

        Args:
            ioc_value (str): IOC value.

        Returns:
            dict[str, Any]: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.IOC}/enrich/{ioc_value}"
        return self._http_request(method="GET", url_suffix=url_suffix)

    def list_mssp_user(self) -> List[dict[str, Any]]:
        """
        List MSSP users.

        Returns:
            List[dict[str, Any]]: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.MSSP}/users-details"
        return self._http_request(method="GET", url_suffix=url_suffix, ok_codes=[HTTPStatus.OK])

    def list_mssp_customer(self) -> List[dict[str, Any]]:
        """
        List MSSP customer.

        Returns:
            List[dict[str, Any]]: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.MSSP}/customers"
        return self._http_request(method="GET", url_suffix=url_suffix, ok_codes=[HTTPStatus.OK])

    def get_alert_csv(self, alert_id: str) -> Response:
        """
        Get alert csv.

        Args:
            alert_id (str): Alert ID.

        Returns:
            Response: API response from Threat Command API.
        """
        url_suffix = f"{V1_PREFIX}/{UrlPrefix.ALERT}/csv-file/{alert_id}"
        return self._http_request(
            method="GET",
            url_suffix=url_suffix,
            resp_type="response",
            ok_codes=[HTTPStatus.OK, HTTPStatus.BAD_REQUEST],
        )


def list_cyber_term_cve_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List the Cyber-term CVEs.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    cyber_term_id = args["cyber_term_id"]

    response = client.list_cyber_term_cve(cyber_term_id=cyber_term_id)
    paginated_response = manual_pagination(response["content"], args)
    mapped_response = list_parser(paginated_response, client.parser.cyber_term_cve_parser)

    return command_result_generate(
        readable_message=ReadableOutputs.CYBER_TERM_CVES.value.format(cyber_term_id),
        outputs=mapped_response,
        headers=["id", "publish_date", "vendor_product"],
        prefix="CVE",
        key_field="id",
        raw_response=response,
    )


def list_cyber_term_ioc_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List the Cyber-term IOCs.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    cyber_term_id = args["cyber_term_id"]
    paginated_response = auto_pagination(
        request_command=client.list_cyber_term_ioc,
        offset_path=["content", "nextOffset"],
        limit=arg_to_number(args.get("limit", 50)),
        page=arg_to_number(args.get("page")),
        page_size=arg_to_number(args.get("page_size")),
        cyber_term_id=args["cyber_term_id"],
        ioc_type=args.get("ioc_type"),
    )
    mapped_response = list_parser(
        values=dict_safe_get(paginated_response, ["content", "iocs"]),
        mapper_command=client.parser.cyber_term_ioc_parser,
    )

    return command_result_generate(
        readable_message=ReadableOutputs.CYBER_TERM_IOCS.value.format(cyber_term_id),
        outputs=mapped_response,
        headers=["value", "type", "is_whitelisted", "updated_date"],
        prefix="IOC",
        key_field="id",
        raw_response=paginated_response,
    )


def list_cyber_term_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List Cyber-terms.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    paginated_response = auto_pagination(
        request_command=client.list_cyber_term,
        offset_path=["nextOffset"],
        limit=arg_to_number(args.get("limit", 50)),
        page=arg_to_number(args.get("page")),
        page_size=arg_to_number(args.get("page_size")),
        search=args.get("search"),
        types_=argToList(args.get("types")),
        severities=argToList(args.get("severities")),
        sectors=argToList(args.get("sectors")),
        countries=argToList(args.get("countries")),
        origin=argToList(args.get("origins")),
        ttp=argToList(args.get("ttps")),
        last_update_from=args.get("last_update_from"),
        last_update_to=args.get("last_update_to"),
    )

    mapped_response = list_parser(
        values=paginated_response["content"],
        mapper_command=client.parser.cyber_term_parser,
    )

    return command_result_generate(
        readable_message=ReadableOutputs.CYBER_TERM.value,
        outputs=mapped_response,
        headers=Headers.LIST_CYBER_TERM.value,
        prefix="CyberTerm",
        key_field="id",
        raw_response=paginated_response,
    )


def list_source_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List IOC sources.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    response = client.list_source()
    fixed_response = [member | {"type": object_type} for object_type in response for member in response[object_type]]

    paginated_response = manual_pagination(fixed_response, args)
    mapped_response = list_parser(paginated_response, response_obj_parser)
    return command_result_generate(
        readable_message=ReadableOutputs.IOC_SOURCE.value,
        outputs=mapped_response,
        headers=["id", "name", "confidence_level", "is_enable", "type"],
        prefix="Source",
        key_field="id",
        raw_response=response,
    )


def create_source_document_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Create a document source.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    args = validate_create_source_document(args)

    name = args["name"]
    response = client.create_document_source(
        name=name,
        description=args["description"],
        confidence_level=args["confidence_level"],
        share=argToBoolean(args.get("share")) if args.get("share") else None,
        severity=args["severity"].lower() if args.get("severity") else None,
        tags=argToList(args.get("tags")),
        domains=argToList(args.get("domains")),
        urls=argToList(args.get("urls")),
        ips=argToList(args.get("ips")),
        hashes=argToList(args.get("hashes")),
        emails=argToList(args.get("emails")),
    )
    source_id = dict_safe_get(response, ["Data", "sourceDetails", "_id"])
    outputs = {"Files": {"id": source_id, "name": name}}
    return command_result_generate(
        readable_message=ReadableOutputs.DOCUMENT_CREATE.value,
        readable_outputs=outputs["Files"],
        outputs=outputs,
        headers=["id", "name"],
        prefix="Source",
        key_field="id",
        raw_response=response,
    )


def delete_source_document_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Delete a document source.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    source_id = args["source_id"]
    client.delete_document_source(source_id=source_id)

    return CommandResults(readable_output=ReadableOutputs.DOCUMENT_DELETE.value.format(source_id))


def create_source_document_ioc_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Create a document source IOCs.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    iocs = handle_iocs(args=args)

    source_id = args["source_id"]

    client.create_document_source_ioc(
        source_id=source_id,
        domains=argToList(args.get("domains")),
        urls=argToList(args.get("urls")),
        ips=argToList(args.get("ips")),
        hashes=argToList(args.get("hashes")),
        emails=argToList(args.get("emails")),
    )

    return CommandResults(readable_output=ReadableOutputs.CREATE_IOC.value.format(iocs, source_id))


def list_system_modules_command(client: Client, *_) -> CommandResults:
    """
    List system modules.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    response = client.list_system_modules()
    fixed_response = dict_to_lowercase(response)
    readable_outputs = [{"module_name": module, "status": status} for module, status in fixed_response.items()]
    return command_result_generate(
        readable_message=ReadableOutputs.SYSTEM_MODULES.value,
        outputs=readable_outputs,
        headers=["module_name", "status"],
        prefix="SystemModule",
        key_field="module_name",
        raw_response=response,
    )


def add_asset_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Add a new asset to asset list.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    asset_type = args["asset_type"]
    asset_value = args["asset_value"]

    client.add_asset(asset_type=asset_type, asset_value=asset_value)
    outputs = {"type": asset_type, "value": asset_value}
    return command_result_generate(
        readable_message=ReadableOutputs.CREATE_ASSET.value.format(asset_value, asset_type),
        outputs=outputs,
        headers=["type", "value"],
        prefix="Asset",
        key_field="value",
        raw_response=outputs,
    )


def delete_asset_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Delete an asset from asset list.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    asset_type = args["asset_type"]
    asset_value = args["asset_value"]

    client.delete_asset(asset_type=asset_type, asset_value=asset_value)

    return CommandResults(readable_output=ReadableOutputs.DELETE_ASSET.value.format(asset_value, asset_type))


def list_assets_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List assets.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    response = client.list_assets(asset_types=argToList(args.get("asset_types")))
    fixed_response = [{"value": asset} | {"type": object_type} for object_type in response for asset in response[object_type]]
    paginated_response = manual_pagination(fixed_response, args)

    return command_result_generate(
        readable_message=ReadableOutputs.LIST_ASSET.value,
        outputs=paginated_response,
        headers=["type", "value"],
        prefix="Asset",
        key_field="value",
        raw_response=response,
    )


def list_asset_types_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List the asset types.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    response = client.list_asset_types()
    paginated_response = manual_pagination(response, args)

    return command_result_generate(
        readable_message=ReadableOutputs.ASSET_TYPES.value,
        outputs=paginated_response,
        headers=["type"],
        prefix="AssetType",
        key_field="value",
        raw_response=response,
    )


def list_cve_command(client: Client, args: dict[str, Any]) -> List[CommandResults]:
    """
    List the account CVEs.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    validate_list_cve(args)
    response = client.list_cve(
        offset=args.get("offset"),
        publish_date_from=args.get("publish_date_from"),
        publish_date_to=args.get("publish_date_to"),
        update_date_from=args.get("update_date_from"),
        update_date_to=args.get("update_date_to"),
        severity_list=argToList(args.get("severity_list", [])),
        cpe_list=argToList(args.get("cpe_list", [])),
        cve_ids=argToList(args.get("cve_ids", [])),
    )
    paginated_response = manual_pagination(response["content"], args)
    mapped_response = list_parser(paginated_response, client.parser.cve_parser)
    return remove_empty_elements(
        [
            command_result_generate(
                readable_message=ReadableOutputs.CVES.value,
                outputs=mapped_response,
                headers=[
                    "id",
                    "published_date",
                    "update_date",
                    "severity",
                    "intsights_score",
                    "cvss_score",
                ],
                prefix="CVE",
                key_field="id",
                raw_response=response,
            ),
            response.get("nextOffset")
            and command_result_generate(
                readable_message=ReadableOutputs.CVE_NEXT_OFFSET.value,
                outputs=response["nextOffset"],
                headers=["offset"],
                prefix="CveNextOffset",
            ),
        ]
    )


def add_cve_command(client: Client, args: dict[str, Any]) -> List[CommandResults]:
    """
    Add CVEs to account list.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    cve_ids = argToList(args["cve_ids"])
    response = client.add_cve(cve_ids=cve_ids)
    return multi_status_handler(
        res=response,
        objects=cve_ids,
        object_key="cveId",
        success_readable=ReadableOutputs.ADD_CVE_SUCCESS.value,
        fail_readable=ReadableOutputs.ADD_CVE_FAIL.value,
    )


def delete_cve_command(client: Client, args: dict[str, Any]) -> List[CommandResults]:
    """
    Delete CVEs from the account list.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
    """
    cve_ids = argToList(args["cve_ids"])
    response = client.delete_cve(cve_ids=cve_ids)
    return multi_status_handler(
        res=response,
        objects=cve_ids,
        object_key="cveId",
        success_readable=ReadableOutputs.DELETE_CVE_SUCCESS.value,
        fail_readable=ReadableOutputs.DELETE_CVE_FAIL.value,
    )


def list_alert_handler_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List alerts handler.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    validate_list_alert(args=args)
    params = {
        "last_updated_from": args.get("last_updated_from"),
        "last_updated_to": args.get("last_updated_to"),
        "alert_type": argToList(args.get("alert_type")),
        "severity": argToList(args.get("severity")),
        "source_type": argToList(args.get("source_type")),
        "network_type": argToList(args.get("network_type")),
        "matched_asset_value": argToList(args.get("matched_asset_value")),
        "source_date_from": args.get("source_date_from"),
        "source_date_to": args.get("source_date_to"),
        "found_date_from": args.get("found_date_from"),
        "found_date_to": args.get("found_date_to"),
        "assigned": arg_to_optional_bool(args.get("assigned")),
        "is_flagged": arg_to_optional_bool(args.get("is_flagged")),
        "is_closed": arg_to_optional_bool(args.get("is_closed")),
        "has_ioc": arg_to_optional_bool(args.get("has_ioc")),
    }

    if alert_id := args.get("alert_id"):
        return get_alert_details_command(client=client, alert_id=alert_id)

    if argToBoolean(args["retrieve_ids_only"]):
        return list_alert_command(client=client, args=args, **params)

    return list_alerts_details_command(client=client, args=args, **params)


def list_alerts_details_command(client: Client, args: dict[str, Any], **params) -> CommandResults:
    """
    Get alerts with complete details.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.
    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    paginated_response = auto_pagination(
        request_command=client.list_alert,
        offset_path=["nextOffset"],
        limit=arg_to_number(args.get("limit", 50)),
        page=arg_to_number(args.get("page")),
        page_size=arg_to_number(args.get("page_size")),
        **params,
    )

    alert_ids = [obj["_id"] for obj in paginated_response["content"]]
    data = [client.parser.alert_get_parser(client.get_alert(alert_id=alert_id)) for alert_id in alert_ids]
    readable_outputs = [alert_readable_outputs_handler(response=alert) for alert in data]
    return command_result_generate(
        readable_message=ReadableOutputs.ALERT_LIST.value,
        readable_outputs=readable_outputs,
        outputs=data,
        headers=Headers.GET_ALERT.value,
        prefix="Alert",
        key_field="id",
        raw_response=data,
    )


def list_alert_command(client: Client, args: dict[str, Any], **params) -> CommandResults:
    """
    list alert ids and updated date.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    paginated_response = auto_pagination(
        request_command=client.list_alert,
        offset_path=["nextOffset"],
        limit=arg_to_number(args.get("limit", 50)),
        page=arg_to_number(args.get("page")),
        page_size=arg_to_number(args.get("page_size")),
        **params,
    )

    mapped_response = list_parser(
        values=paginated_response.get("content", []),
        mapper_command=response_obj_parser,
    )

    return command_result_generate(
        readable_message=ReadableOutputs.ALERT_LIST.value,
        outputs=mapped_response,
        headers=["id", "update_date"],
        prefix="Alert",
        key_field="id",
        raw_response=paginated_response,
    )


def get_alert_details_command(client: Client, alert_id: str) -> CommandResults:
    """
    Get alert with complete details.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    response = client.get_alert(alert_id=alert_id)
    mapped_response = client.parser.alert_get_parser(response)
    readable_outputs = alert_readable_outputs_handler(response=mapped_response)

    return command_result_generate(
        readable_message=ReadableOutputs.ALERT_GET.value.format(alert_id),
        readable_outputs=readable_outputs,
        outputs=mapped_response,
        headers=Headers.GET_ALERT.value,
        prefix="Alert",
        key_field="id",
        raw_response=response,
    )


def create_alert_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Create a new alert.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    validate_create_alert(args=args)
    response = client.create_alert(
        title=args["title"],
        description=args["description"],
        type_=args.get("type"),
        sub_type=args.get("sub_type"),
        severity=args["severity"],
        source_type=args["source_type"],
        source_network_type=args["source_network_type"],
        source_date=args.get("source_date"),
        found_date=args.get("found_date"),
        image_entry_ids=argToList(args.get("image_entry_ids")),
        scenario=args.get("scenario"),
        source_url=args.get("source_url"),
    )
    outputs = {"id": response.content.decode()}
    return command_result_generate(
        readable_message=ReadableOutputs.ALERT_CREATE.value,
        outputs=outputs,
        headers=["id"],
        prefix="Alert",
        key_field="id",
        raw_response=outputs,
    )


def close_alert_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Close alert.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    validate_close_alert(args)

    alert_id = args["alert_id"]

    client.close_alert(
        alert_id=alert_id,
        reason=args["reason"],
        comment=args.get("comment"),
        is_hidden=argToBoolean(args["is_hidden"]),
        rate=arg_to_number(args.get("rate")),
    )
    outputs = {"id": alert_id, "is_closed": True}
    return command_result_generate(
        readable_message=ReadableOutputs.ALERT_CLOSE.value.format(alert_id),
        outputs=outputs,
        headers=["id", "is_closed"],
        prefix="Alert",
        key_field="id",
        raw_response=outputs,
    )


def update_alert_severity_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Update the alert severity.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    validate_alert_ioc_severity(args)

    alert_id = args["alert_id"]
    severity = args["severity"]

    client.update_alert_severity(alert_id=alert_id, severity=severity)
    outputs = {"id": alert_id, "severity": severity}
    return command_result_generate(
        readable_message=ReadableOutputs.ALERT_SEVERITY.value.format(alert_id, severity),
        outputs=outputs,
        headers=["id", "severity"],
        prefix="Alert",
        key_field="id",
        raw_response=outputs,
    )


def assign_alert_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Assign alert to user.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    validate_assign_alert(args)
    alert_id = args["alert_id"]
    user_id = args["user_id"]

    client.assign_alert(alert_id=alert_id, user_id=user_id, is_mssp=argToBoolean(args.get("is_mssp")))
    outputs = {"id": alert_id, "assignees": [user_id]}
    return command_result_generate(
        readable_message=ReadableOutputs.ALERT_ASSIGN.value.format(alert_id, user_id),
        outputs=outputs,
        headers=["id", "assignees"],
        prefix="Alert",
        key_field="id",
        raw_response=outputs,
    )


def unassign_alert_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Unassign alert.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    alert_id = args["alert_id"]

    client.unassign_alert(alert_id=alert_id)

    outputs = {"id": alert_id, "assignees": None}
    return command_result_generate(
        readable_message=ReadableOutputs.ALERT_UNASSIGN.value.format(alert_id),
        outputs=outputs,
        headers=["id", "assignees"],
        prefix="Alert",
        key_field="id",
        raw_response=outputs,
    )


def reopen_alert_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Re-open closed alert.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    alert_id = args["alert_id"]

    client.reopen_alert(alert_id=alert_id)
    return CommandResults(readable_output=ReadableOutputs.ALERT_REOPEN.value.format(alert_id))


def tag_alert_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Add tag to alert.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    alert_id = args["alert_id"]
    tag_name = args["tag_name"]

    client.tag_alert(alert_id=alert_id, tag_name=tag_name)

    return CommandResults(readable_output=ReadableOutputs.ALERT_TAG_ADD.value.format(alert_id, tag_name))


def untag_alert_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Remove tag from alert.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    alert_id = args["alert_id"]
    tag_id = args["tag_id"]

    client.untag_alert(alert_id=alert_id, tag_id=tag_id)

    return CommandResults(readable_output=ReadableOutputs.ALERT_TAG_REMOVE.value.format(alert_id, tag_id))


def send_mail_alert_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Send a mail with alert details.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    alert_id = args["alert_id"]
    email_addresses = argToList(args["email_addresses"])
    content = args["content"]

    client.send_mail_alert(alert_id=alert_id, email_addresses=email_addresses, content=content)

    return CommandResults(readable_output=ReadableOutputs.ALERT_MAIL.value.format(alert_id, email_addresses))


def analyst_ask_alert_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Send a question to an analyst about the requested alert.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    alert_id = args["alert_id"]
    question = args["question"]

    client.analyst_ask_alert(alert_id=alert_id, question=question)
    return CommandResults(readable_output=ReadableOutputs.ALERT_ANALYST.value.format(alert_id))


def list_alert_conversation_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List alert's analyst messages.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    alert_id = args["alert_id"]

    response = client.list_alert_conversation(alert_id=alert_id)
    if response.status_code == HTTPStatus.NO_CONTENT:
        return CommandResults(readable_output=ReadableOutputs.ALERT_NO_CONVERSATION_LIST.value)
    response_json = response.json()
    mapped_response = [dict_to_lowercase(msg) for msg in response_json]
    outputs = {"id": alert_id, "Message": mapped_response}
    return command_result_generate(
        readable_message=ReadableOutputs.ALERT_CONVERSATION_LIST.value,
        outputs=outputs,
        headers=["initiator", "message", "date"],
        prefix="Alert",
        key_field="id",
        raw_response=response_json,
        readable_outputs=mapped_response,
    )


def list_alert_activity_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List alert activity logs.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    alert_id = args["alert_id"]

    response = client.list_alert_activity(alert_id=alert_id)
    mapped_response = list_parser(response, client.parser.alert_activity_parser)
    outputs = {"ActivityLog": mapped_response, "id": alert_id}
    return command_result_generate(
        readable_message=ReadableOutputs.ALERT_ACTIVITY.value.format(alert_id),
        readable_outputs=mapped_response,
        outputs=outputs,
        headers=["id", "type", "update_date", "sub_types", "initiator"],
        prefix="Alert",
        key_field="id",
        raw_response=response,
    )


def add_alert_note_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Add a note to alert.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    alert_id = args["alert_id"]
    client.add_alert_note(
        alert_id=alert_id,
        note=args["note"],
        file_entry_ids=argToList(args.get("entry_ids")),
    )
    return CommandResults(readable_output=ReadableOutputs.ALERT_ADD_NOTE.value.format(alert_id))


def get_alert_blocklist_status_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Get alert's blocklist status.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    alert_id = args["alert_id"]

    response = client.get_alert_blocklist(alert_id=alert_id)
    mapped_response = [dict_to_lowercase(msg) for msg in response]
    outputs = {"id": alert_id, "BlockList": mapped_response}
    return command_result_generate(
        readable_message=ReadableOutputs.ALERT_BLOCKLIST_GET.value.format(alert_id),
        outputs=outputs,
        headers=["value", "status"],
        prefix="Alert",
        key_field="id",
        raw_response=response,
        readable_outputs=mapped_response,
    )


def update_alert_blocklist_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Change selected IOCs blocklist status.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    validate_update_alert_blocklist(args)

    alert_id = args["alert_id"]
    blocklist_status = args["blocklist_status"]

    client.update_alert_blocklist(
        alert_id=alert_id,
        domains=argToList(args.get("domains")),
        urls=argToList(args.get("urls")),
        ips=argToList(args.get("ips")),
        emails=argToList(args.get("emails")),
        blocklist_status=blocklist_status,
    )

    return CommandResults(readable_output=ReadableOutputs.ALERT_BLOCKLIST_UPDATE.value.format(blocklist_status))


def list_alert_image_command(
    client: Client, args: dict[str, Any]
) -> List[CommandResults | List[Dict[str, Any]]] | CommandResults:
    """
    List alert images by alert ID.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    images = []
    alert_id = args["alert_id"]
    complete_alert = client.get_alert(alert_id=alert_id)
    img_ids = dict_safe_get(complete_alert, ["Details", "Images"], [])
    images = [
        fileResult(filename=f"{img}.png", data=client.get_alert_image(img).content, file_type=EntryType.ENTRY_INFO_FILE)
        for img in img_ids
    ]
    return (
        [
            CommandResults(readable_output=ReadableOutputs.ALERT_IMAGES.value.format(alert_id)),
            images,
        ]
        if images
        else CommandResults(readable_output=ReadableOutputs.ALERT_NO_IMAGES.value.format(alert_id))
    )


def takedown_alert_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Send a takedown request for alert.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    alert_id = args["alert_id"]
    client.takedown_alert(
        alert_id=alert_id,
        target=args["target"],
        close_alert_after_success=argToBoolean(args["close_alert_after_success"]),
    )

    return CommandResults(readable_output=ReadableOutputs.ALERT_TAKEDOWN.value.format(alert_id))


def get_takedown_alert_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Get the alert's takedown status.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    alert_id = args["alert_id"]
    response = client.get_takedown_alert(alert_id=alert_id)
    outputs = {"id": alert_id, "takedown_status": response.content.decode()}
    return command_result_generate(
        readable_message=ReadableOutputs.ALERT_TAKEDOWN_STATUS.value.format(alert_id),
        outputs=outputs,
        headers=["takedown_status"],
        prefix="Alert",
        key_field="id",
        raw_response=outputs,
        readable_outputs=outputs,
    )


def list_alert_type_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List alert types.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    response = client.list_alert_type()
    fixed_response = [{"type": object_type, "sub_type": member} for object_type in response for member in response[object_type]]
    paginated_response = manual_pagination(fixed_response, args)

    return command_result_generate(
        readable_message=ReadableOutputs.ALERT_TYPES.value,
        outputs=paginated_response,
        headers=["type", "sub_type"],
        prefix="AlertType",
        key_field="sub_type",
        raw_response=response,
    )


def list_alert_source_type_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List alert source types.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    response = client.list_alert_source_type()
    paginated_response = manual_pagination(response, args)
    return command_result_generate(
        readable_message=ReadableOutputs.ALERT_SOURCE_TYPES.value,
        outputs=paginated_response,
        headers=["source_type"],
        prefix="AlertSourceType",
        raw_response=response,
    )


def list_alert_scenario_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List alert scenarios.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    response = client.list_alert_scenario(type_=args.get("type"), sub_type=args.get("sub_type"))
    paginated_response = manual_pagination(response, args)
    fixed_response = [dict_to_lowercase(obj) for obj in paginated_response]
    return command_result_generate(
        readable_message=ReadableOutputs.SCENARIO_LIST.value,
        outputs=fixed_response,
        headers=["scenario", "description", "type", "subtype"],
        prefix="Scenario",
        key_field="scenario",
        raw_response=response,
    )


def report_alert_ioc_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Report alert IOC.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    alert_id = args["alert_id"]
    client.report_alert_ioc(alert_id=alert_id, external_sources=argToList(args["external_sources"]))

    return CommandResults(readable_output=ReadableOutputs.ALERT_REPORT.value.format(alert_id))


def list_account_user_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List account users.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    validate_list_account_user(args)
    response = client.list_account_user(
        user_type=args.get("user_type"),
        user_email=args.get("user_email"),
        user_id=args.get("user_id"),
    )
    paginated_response = manual_pagination(response, args)
    mapped_response = list_parser(paginated_response, response_obj_parser)

    return command_result_generate(
        readable_message=ReadableOutputs.ACCOUNT_USER_LIST.value,
        outputs=mapped_response,
        headers=["id", "email", "first_name", "last_name", "role", "is_deleted"],
        prefix="AccountUser",
        key_field="id",
        raw_response=response,
    )


@polling_function(
    name="threat-command-ioc-search",
    interval=arg_to_number(demisto.args().get("interval_in_seconds", DEFAULT_INTERVAL)),
    timeout=arg_to_number(demisto.args().get("timeout_in_seconds", DEFAULT_TIMEOUT)),
    requires_polling_arg=False,
)
def search_ioc_handler_command(args: dict[str, Any], client: Client, execution_metrics: ExecutionMetrics) -> PollResult:
    """
    List IOCs handler.
    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.
        execution_metrics (ExecutionMetrics): Execution metrics.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    # validate_list_alert(args=args)
    if argToBoolean(args["enrichment"]):
        # Enrich IOC - Blocked.
        return enrich_ioc_handler(client=client, args=args, execution_metrics=execution_metrics)

    if ioc_value := args.get("ioc_value"):
        # Get IOC by value
        return PollResult(
            response=get_ioc_handler(client=client, ioc_value=ioc_value),
            continue_to_poll=False,
        )

    # Get IOC By filter
    validate_list_ioc(args)
    return PollResult(
        response=list_ioc_handler(client=client, args=args),
        continue_to_poll=False,
    )


def enrich_ioc_handler(client: Client, args: dict[str, Any], execution_metrics: ExecutionMetrics) -> PollResult:
    """
    Enrich IOC with details.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.
        execution_metrics (ExecutionMetrics): Execution metrics.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    ioc_value = args["ioc_value"]
    response = client.enrich_ioc(ioc_value=ioc_value)
    command_results = []
    status = response["Status"]
    if status == "QuotaExceeded":
        execution_metrics.quota_error += 1
        command_results.append(CommandResults(readable_output=ReadableErrors.ENRICH_FAIL.value.format(status)))
        command_results.append(cast(CommandResults, execution_metrics.metrics))
        return PollResult(
            response=command_results,
            continue_to_poll=False,
        )
    if status == "Failed":
        execution_metrics.general_error += 1
        command_results.append(CommandResults(readable_output=ReadableErrors.ENRICH_FAIL.value.format(status)))
        command_results.append(cast(CommandResults, execution_metrics.metrics))
        return PollResult(
            response=command_results,
            continue_to_poll=False,
        )
    if response["Status"] == "Done":
        execution_metrics.success += 1
        filtered_response = client.parser.ioc_enrich_parser(response["Data"])
        command_results.append(
            command_result_generate(
                readable_message=ReadableOutputs.ENRICH_GET.value.format(ioc_value),
                outputs=filtered_response,
                prefix="IOC",
                headers=Headers.ENRICH_IOC.value,
                key_field="value",
                raw_response=response,
            )
        )
        command_results.append(cast(CommandResults, execution_metrics.metrics))
        return PollResult(
            response=command_results,
            continue_to_poll=False,
        )
    return PollResult(
        response=response["Status"],
        continue_to_poll=True,
        args_for_next_run=args,
    )


def get_ioc_handler(client: Client, ioc_value: str) -> CommandResults:
    """
    Get IOC with details.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    response = client.get_ioc(ioc_value=ioc_value)
    mapped_response = client.parser.ioc_get_parser(response)
    return command_result_generate(
        readable_message=ReadableOutputs.IOC_GET.value.format(ioc_value),
        outputs=mapped_response,
        headers=Headers.GET_IOC.value,
        prefix="IOC",
        key_field="id",
        raw_response=response,
    )


def list_ioc_handler(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List IOC by filters.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    paginated_response = auto_pagination(
        request_command=client.list_ioc,
        offset_path=["nextOffset"],
        limit=arg_to_number(args.get("limit", 50)),
        page=arg_to_number(args.get("page")),
        page_size=arg_to_number(args.get("page_size")),
        last_updated_from=args.get("last_updated_from"),
        last_updated_to=args.get("last_updated_to"),
        last_seen_from=args.get("last_seen_from"),
        last_seen_to=args.get("last_seen_to"),
        first_seen_from=args.get("first_seen_from"),
        first_seen_to=args.get("first_seen_to"),
        status=args.get("status"),
        type_list=argToList(args.get("type_list")),
        severity_list=argToList(args.get("severity_list")),
        whitelisted=args.get("whitelisted"),
        source_ids=argToList(args.get("source_ids")),
        kill_chain_phases=argToList(args.get("kill_chain_phases")),
    )
    mapped_response = list_parser(paginated_response["content"], client.parser.ioc_get_parser)

    return command_result_generate(
        readable_message=ReadableOutputs.IOC_LIST.value,
        outputs=mapped_response,
        headers=Headers.GET_IOC.value,
        prefix="IOC",
        key_field="id",
        raw_response=paginated_response,
    )


def add_tags_ioc_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Add tags to IOC.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    ioc_value = args["ioc_value"]
    tag_values = argToList(args["tag_values"])

    client.tags_ioc(ioc_value=ioc_value, tag_values=tag_values)

    return CommandResults(readable_output=ReadableOutputs.IOC_TAG_ADD.value.format(ioc_value, tag_values))


def update_ioc_severity_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Update severity for IOCs.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    severity = args["severity"]

    iocs = handle_iocs(args=args)

    validate_alert_ioc_severity(args)
    client.update_ioc_severity(
        severity=severity,
        ioc_values=iocs,
    )

    return CommandResults(readable_output=ReadableOutputs.UPDATE_IOC_SEVERITY.value.format(iocs, severity))


def add_ioc_comment_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Add comment to IOCs.

    Args:

        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    comment = args["comment"]

    iocs = handle_iocs(args=args)
    client.add_ioc_comment(
        comment=comment,
        ioc_values=iocs,
    )

    return CommandResults(readable_output=ReadableOutputs.ADD_IOC_COMMENT.value.format(iocs, comment))


def update_account_whitelist_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Update account whitelist.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    is_whitelisted = args["is_whitelisted"]

    iocs = handle_iocs(args=args)
    validate_update_account_whitelist(args)
    client.update_account_whitelist(
        is_whitelisted=is_whitelisted,
        ioc_values=iocs,
    )

    return CommandResults(readable_output=ReadableOutputs.UPDATE_ACCOUNT_WHITELIST.value.format(iocs, is_whitelisted))


def remove_account_whitelist_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Remove IOCs from account whitelist.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    iocs = handle_iocs(args=args)
    client.remove_account_whitelist(
        ioc_values=iocs,
    )

    return CommandResults(readable_output=ReadableOutputs.REMOVE_ACCOUNT_WHITELIST.value.format(iocs))


def add_ioc_blocklist_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Add IOCs to remediation blocklist.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.
    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """

    iocs = handle_iocs(args=args)
    client.add_ioc_blocklist(
        ioc_values=iocs,
    )

    return CommandResults(readable_output=ReadableOutputs.ADD_IOC_BLOCKLIST.value.format(iocs))


def remove_ioc_blocklist_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Remove IOCs from remediation blocklist.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """

    iocs = handle_iocs(args=args)
    client.remove_ioc_blocklist(
        ioc_values=iocs,
    )

    return CommandResults(readable_output=ReadableOutputs.REMOVE_IOC_BLOCKLIST.value.format(iocs))


def search_mention_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Search mentions.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    search = args["search"]
    page_number = arg_to_number(args["page_number"])
    validate_search_mentions(args)
    if not isinstance(page_number, int):
        raise ValueError(ReadableErrors.NUMBER.value)
    response = client.search_mention(
        search=search,
        report_date=args.get("report_date"),
        page_number=page_number,
        source_types=argToList(args.get("source_types")),
        only_dark_web=argToBoolean(args.get("only_dark_web")),
        highlight_tags=argToBoolean(args.get("highlight_tags")),
    )
    mapped_response = list_parser(response["Data"], client.parser.mention_parser)
    return command_result_generate(
        readable_message=ReadableOutputs.MENTIONS.value.format(search, page_number),
        outputs=mapped_response,
        headers=Headers.MENTION.value,
        prefix="Mentions",
        key_field="id",
        raw_response=response,
    )


def usage_quota_enrichment_command(client: Client, *_) -> CommandResults:
    """
    Get enrichment quota.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    response = client.usage_quota_enrichment()
    mapped_response = response_obj_parser(dict_=response["EnrichIocsQuota"])
    return command_result_generate(
        readable_message=ReadableOutputs.ENRICH_QUOTA.value,
        outputs=mapped_response,
        headers=["time_period", "total", "remaining"],
        prefix="IOCsQuota",
        raw_response=response,
    )


def list_mssp_user_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List MSSP users.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    response = client.list_mssp_user()
    paginated_response = manual_pagination(response, args)
    mapped_response = list_parser(paginated_response, response_obj_parser)
    return command_result_generate(
        readable_message=ReadableOutputs.MSSP_USER_LIST.value,
        outputs=mapped_response,
        headers=["id", "email", "role", "is_deleted"],
        prefix="MsspUser",
        key_field="id",
        raw_response=response,
    )


def list_mssp_customer_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    List MSSP customers.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    response = client.list_mssp_customer()
    paginated_response = manual_pagination(response, args)
    mapped_response = list_parser(paginated_response, response_obj_parser)
    return command_result_generate(
        readable_message=ReadableOutputs.MSSP_CUSTOMER_LIST.value,
        outputs=mapped_response,
        headers=["id", "company_name", "status", "note"],
        prefix="MsspCustomer",
        key_field="id",
        raw_response=response,
    )


def get_alert_csv_command(client: Client, args: dict[str, Any]) -> List[CommandResults | Dict[str, Any]] | CommandResults:
    """
    Get alert CSV file if exists.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        List[CommandResults | Dict[str, Any]] | CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    alert_id = args["alert_id"]
    csv_response = client.get_alert_csv(alert_id)
    if csv_response.status_code != HTTPStatus.OK:
        return CommandResults(readable_output=ReadableOutputs.ALERT_NO_CSV.value.format(alert_id))
    csv_file = fileResult(filename=f"{alert_id}.csv", data=csv_response.content, file_type=EntryType.ENTRY_INFO_FILE)
    decoded_content = csv_response.content.decode()
    tab_based_content = list(csv.DictReader(decoded_content.splitlines(), delimiter="\t"))
    content = list(csv.DictReader(decoded_content.splitlines(), delimiter=","))
    if tab_based_content and content and (len(tab_based_content[0]) > len(content[0])):
        content = tab_based_content
    outputs = {"alert_id": alert_id, "content": content}
    return [
        CommandResults(
            readable_output=ReadableOutputs.ALERT_CSV.value.format(alert_id),
            outputs_prefix=f"{INTEGRATION_ENTRY_CONTEXT}.CSV",
            outputs_key_field="alert_id",
            outputs=outputs,
            raw_response=outputs,
        ),
        csv_file,
    ]


@polling_function(
    name="file",
    interval=arg_to_number(demisto.args().get("interval_in_seconds", DEFAULT_INTERVAL)),
    timeout=arg_to_number(demisto.args().get("timeout_in_seconds", DEFAULT_TIMEOUT)),
    requires_polling_arg=False,
)
def file_command(args: dict[str, Any], client: Client, execution_metrics: ExecutionMetrics) -> PollResult:
    """
    Enrich file IOC (Generic reputation command).

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.
        execution_metrics (ExecutionMetrics): Execution metrics.

    Returns:
        PollResult: outputs, readable outputs and raw response for XSOAR.
    """
    return reputation_handler(args, client, file_reputation_handler, IOCType.FILE.value.lower(), execution_metrics)


@polling_function(
    name="ip",
    interval=arg_to_number(demisto.args().get("interval_in_seconds", DEFAULT_INTERVAL)),
    timeout=arg_to_number(demisto.args().get("timeout_in_seconds", DEFAULT_TIMEOUT)),
    requires_polling_arg=False,
)
def ip_command(args: dict[str, Any], client: Client, execution_metrics: ExecutionMetrics) -> PollResult:
    """
    Enrich ip IOC (Generic reputation command).

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.
        execution_metrics (ExecutionMetrics): Execution metrics.

    Returns:
        PollResult: outputs, readable outputs and raw response for XSOAR.
    """
    return reputation_handler(args, client, ip_reputation_handler, IOCType.IP.value.lower(), execution_metrics)


@polling_function(
    name="url",
    interval=arg_to_number(demisto.args().get("interval_in_seconds", DEFAULT_INTERVAL)),
    timeout=arg_to_number(demisto.args().get("timeout_in_seconds", DEFAULT_TIMEOUT)),
    requires_polling_arg=False,
)
def url_command(args: dict[str, Any], client: Client, execution_metrics: ExecutionMetrics) -> PollResult:
    """
    Enrich URL IOC (Generic reputation command).

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.
        execution_metrics (ExecutionMetrics): Execution metrics.

    Returns:
        PollResult: outputs, readable outputs and raw response for XSOAR.
    """

    return reputation_handler(args, client, url_reputation_handler, IOCType.URL.value.lower(), execution_metrics)


@polling_function(
    name="domain",
    interval=arg_to_number(demisto.args().get("interval_in_seconds", DEFAULT_INTERVAL)),
    timeout=arg_to_number(demisto.args().get("timeout_in_seconds", DEFAULT_TIMEOUT)),
    requires_polling_arg=False,
)
def domain_command(args: dict[str, Any], client: Client, execution_metrics: ExecutionMetrics) -> PollResult:
    """
    Enrich domain IOC (Generic reputation command).

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.
        execution_metrics (ExecutionMetrics): Execution metrics.

    Returns:
        PollResult: outputs, readable outputs and raw response for XSOAR.
    """
    return reputation_handler(args, client, domain_reputation_handler, IOCType.DOMAIN.value.lower(), execution_metrics)


def reputation_handler(
    args: dict[str, Any], client: Client, handler_command: Callable, key: str, execution_metrics: ExecutionMetrics
) -> PollResult:
    """
    Handle with all reputation commands.

    Args:
        client (Client): Threat Command API client.
        args (Dict[str, Any]): Command arguments from XSOAR.
        handler_command (Callable): Handler command for each command.
        key (str): Key for the IOC.
        execution_metrics (ExecutionMetrics): Execution metrics.

    Returns:
        PollResult: outputs, readable outputs and raw response for XSOAR.
    """
    ioc_values: List[str] = argToList(args[key])

    responses = [client.enrich_ioc(ioc_value=ioc_value) for ioc_value in ioc_values]

    command_results = []
    done_responses = list(filter(lambda response: response["Status"] == "Done", responses))
    failed_responses = list(filter(lambda response: response["Status"] == "Failed", responses))
    quota_responses = list(filter(lambda response: response["Status"] == "QuotaExceeded", responses))
    for response in done_responses + failed_responses + quota_responses:
        ioc_values.remove(response["OriginalValue"])

    if not ioc_values:
        execution_metrics.success += len(done_responses)
        execution_metrics.general_error += len(failed_responses)
        execution_metrics.quota_error += len(quota_responses)
        for response in done_responses:
            command_results.append(handler_command(client=client, obj=response, obj_id=response["OriginalValue"]))
        for response in failed_responses + quota_responses:
            command_results.append(CommandResults(readable_output=ReadableErrors.ENRICH_FAIL.value.format(response["Status"])))

        command_results.append(cast(CommandResults, execution_metrics.metrics))

        return PollResult(response=command_results, continue_to_poll=False, args_for_next_run=args)

    return PollResult(
        partial_result=CommandResults(readable_output=f'Waiting for "{ioc_values}" to finish...'),
        response=command_results,
        continue_to_poll=True,
        args_for_next_run=args,
    )


""" HELPER FUNCTIONS """


def file_reputation_handler(client: Client, obj: dict[str, Any], obj_id: str) -> CommandResults:
    """
    Handle with file enrichment response.

    Args:
        client (Client): Threat Command API client.
        obj (dict[str, Any]): File response.
        obj_id (str): File value.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    command_args = client.parser.file_reputation_parser(obj=obj, hash_=obj_id, reliability=client.reliability)
    file_indicator = Common.File(**command_args)
    command_args.pop("dbot_score")
    return CommandResults(
        outputs_prefix=f"{INTEGRATION_ENTRY_CONTEXT}.File",
        outputs_key_field="sha256",
        indicator=file_indicator,
        readable_output=tableToMarkdown(f"Rapid7 Threat Command - Hash Reputation for: {obj_id}", t=command_args),
        outputs=command_args,
        raw_response=obj,
    )


def ip_reputation_handler(client: Client, obj: Dict[str, Any], obj_id: str) -> CommandResults:
    """
    Handle with IP enrichment response.

    Args:
        client (Client): Threat Command API client.
        obj (dict[str, Any]): IP response.
        obj_id (str): IP value.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    command_args = client.parser.ip_reputation_parser(obj=obj, ip=obj_id, reliability=client.reliability)
    ip_indicator = Common.IP(**command_args)
    command_args.pop("dbot_score")
    return CommandResults(
        outputs_prefix=f"{INTEGRATION_ENTRY_CONTEXT}.IP",
        outputs_key_field="ip",
        indicator=ip_indicator,
        readable_output=tableToMarkdown(f"Rapid7 Threat Command - IP Reputation for: {obj_id}", command_args),
        outputs=command_args,
        raw_response=obj,
    )


def url_reputation_handler(client: Client, obj: Dict[str, Any], obj_id: str) -> CommandResults:
    """
    Handle with URL enrichment response.

    Args:
        client (Client): Threat Command API client.
        obj (dict[str, Any]): URL response.
        obj_id (str): URL value.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    command_args = client.parser.url_reputation_parser(obj=obj, url=obj_id, reliability=client.reliability)
    url_indicator = Common.URL(**command_args)
    command_args.pop("dbot_score")

    return CommandResults(
        outputs_prefix=f"{INTEGRATION_ENTRY_CONTEXT}.URL",
        outputs_key_field="url",
        indicator=url_indicator,
        readable_output=tableToMarkdown(f"Rapid7 Threat Command - URL Reputation for: {obj_id}", command_args),
        outputs=command_args,
        raw_response=obj,
    )


def domain_reputation_handler(client: Client, obj: Dict[str, Any], obj_id: str) -> CommandResults:
    """
    Handle with domain enrichment response.

    Args:
        client (Client): Threat Command API client.
        obj (dict[str, Any]): Domain response.
        obj_id (str): Domain value.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    command_args = client.parser.domain_reputation_parser(obj=obj, domain=obj_id, reliability=client.reliability)
    domain_indicator = Common.Domain(**command_args)
    del command_args["dbot_score"]
    del command_args["dns_records"]
    return CommandResults(
        outputs_prefix=f"{INTEGRATION_ENTRY_CONTEXT}.Domain",
        outputs_key_field="domain",
        indicator=domain_indicator,
        readable_output=tableToMarkdown(
            f"Rapid7 Threat Command - domain Reputation for: {obj_id}",
            command_args,
        ),
        outputs=command_args,
        raw_response=obj,
    )


def get_dbotscore(reliability: str, indicator: str = None, is_known_ioc: bool | None = None) -> Common.DBotScore:
    """
    Get XSOAR score for the indicator.
    Args:
        reliability (str): Reliability of the source providing the intelligence data.
        indicator (str, optional): Indicator response.
            Defaults to None.
        is_known_ioc (bool, optional): Whether the IOC is known to Threat Command.
            Defaults to None.
    Returns:
        Common.DBotScore: DBot Score according to the disposition.
    """
    if is_known_ioc:
        score = Common.DBotScore.BAD

    elif is_known_ioc:
        score = Common.DBotScore.GOOD

    else:
        score = Common.DBotScore.NONE

    return Common.DBotScore(
        indicator=indicator,
        indicator_type=DBotScoreType.FILE,
        integration_name="ThreatCommand",
        reliability=reliability,
        score=score,
    )


def get_enrich_hashes(response: dict[str, Any]) -> dict[str, Any]:
    """
    Get hashes values from hash enrichment response.

    Args:
        response (dict[str, Any]): Hash enrichment response from Threat Command API.

    Returns:
        dict[str, Any]: Hashes dictionary.
    """
    return (
        {hash["Type"]: hash["Value"] for hash in dict_safe_get(response, ["Data", "RelatedHashes"], [])}
        if isinstance(dict_safe_get(response, ["Data", "RelatedHashes"]), list)
        else {}
    )


def get_enrich_file_nams(response: dict[str, Any]) -> List[str]:
    """
    Get file names from enrichment response.

    Args:
        response (dict[str, Any]): Hash enrichment response from Threat Command API.

    Returns:
        List[str]: File names.
    """
    return remove_empty_elements(
        [
            detection.get("Result") if detection.get("Result") != "" else None
            for detection in dict_safe_get(response, ["Data", "AntivirusDetections"], [])
        ]
    )


def remove_whitespaces(str_: str | None) -> str | None:
    """
    Remove whitespaces from string.

    Args:
        str_ (str | None): String to remove whitespaces from.

    Returns:
        str | None: String without whitespaces.
    """
    if str_:
        return str_.replace(" ", "")
    return None


def files_handler(file_ids: List[str], is_image: bool = False) -> List[dict[str, Any]]:
    """
    Read XSOAR file ids and organized them in list.

    Args:
        file_ids (List[str]): XSOAR file ids.
        is_image (bool, optional): is the file are images for creating alert?. Defaults to False.

    Returns:
        List[dict[str, Any]]: List of the files with data.
    """
    files_data = []
    for image_id in file_ids:
        file_data = demisto.getFilePath(image_id)
        file_type = pathlib.Path(file_data["name"]).suffix[1:]
        with open(file_data["path"], "rb") as f:
            files_data.append(
                {
                    "Data": base64.b64encode(f.read()).decode(),
                    "Type": "jpeg" if file_type == "jpg" else file_type,
                    "Name": file_data["name"] if not is_image else None,
                }
            )
    return remove_empty_elements(files_data)


def command_result_generate(
    readable_message: str,
    outputs: Dict[str, Any] | List[Any],
    headers: List[str],
    prefix: str,
    readable_outputs: Dict[str, Any] | List | None = None,
    key_field: str | None = None,
    raw_response: Dict[str, Any] | List[Any] | None = None,
) -> CommandResults:
    """
    Generate CommandResults object with readable output.

    Args:
        readable_message (str): Readable output message.
        outputs (Dict[str, Any] | List[Any]): Outputs to XSOAR outputs.
        headers (List[str]): Headers for readable outputs table.
        prefix (str): Outputs prefix.
        readable_outputs (Dict[str, Any] | List | None, optional): Readable outputs to show. Defaults to None.
        key_field (str): Outputs key field.
        raw_response (Dict[str, Any] | List[Any]): Raw response to XSOAR outputs.

    Returns:
        CommandResults: outputs, readable outputs and raw response for XSOAR.
    """
    return CommandResults(
        readable_output=tableToMarkdown(
            name=readable_message,
            t=readable_outputs if readable_outputs else outputs,
            headers=headers,
            headerTransform=string_to_table_header,
            removeNull=True,
        ),
        outputs_prefix=f"{INTEGRATION_ENTRY_CONTEXT}.{prefix}",
        outputs_key_field=key_field,
        outputs=outputs,
        raw_response=raw_response,
    )


def manual_pagination(response: List[Any], args: dict[str, Any]) -> List[Any]:
    """
    Executing Manual paginate_results (using the limit argument).

    Args:
        response (List[dict[str, Any]]): API response.
        args (dict[str, Any]): Command arguments from XSOAR.

    Returns:
        List[dict[str, Any]]: Paginated results.
    """

    if argToBoolean(args.get("all_results", False)):
        return response

    limit = arg_to_number(args.get("limit", 50))

    if limit and limit < 1:
        raise ValueError(ReadableErrors.LIMIT.value)

    return response[:limit]


def list_parser(values: List[dict[str, Any]], mapper_command: Callable) -> List[dict[str, Any]]:
    """
    Handle with parse list of objects.

    Args:
        values (List[dict[str, Any]]): List of objects to map.
        mapper_command (Callable): The object parse command.

    Returns:
        List[dict[str, Any]]: Parsed list.
    """
    return [mapper_command(obj) for obj in values]


def auto_pagination(
    request_command: Callable,
    offset_path: List[str],
    limit: int | None,
    page: int | None,
    page_size: int | None,
    offset: str | None = None,
    **kwargs,
) -> dict[str, Any]:
    """
    Handle with pagination when the API supports pagination.

    Args:
        request_command (Callable): List request command.
        offset_path (List[str]): The path to the offset arg (in order to handle with page, page_size).
        limit (int): Limit for pagination.
        page (int | None): Page for pagination
        page_size (int | None): Page size for pagination
        offset (str | None, optional): Offset for pagination. Defaults to None.

    Raises:
        ValueError: Error with pagination when there is no offset arg.

    Returns:
        dict[str, Any]: Paginated response.
    """
    command_args = copy.deepcopy(kwargs)
    command_args["offset"] = offset
    if page and page_size:
        if page == 1:
            command_args["limit"] = page_size
            return request_command(**command_args)
        calculate = (page - 1) * page_size
        command_args["limit"] = calculate if calculate < API_MAX_LIMIT else calculate - calculate % page_size
        offset = dict_safe_get(request_command(**command_args), offset_path)
        if calculate > API_MAX_LIMIT:
            auto_pagination(
                request_command=request_command,
                offset_path=offset_path,
                page=int(page - command_args["limit"] / page_size),
                page_size=page_size,
                **command_args,
            )
        if offset is None:
            raise ValueError("Error with pagination.")

        command_args["limit"] = page_size
        command_args["offset"] = offset
        return request_command(**command_args)
    command_args["limit"] = limit
    return request_command(**command_args)


def map_ioc_list(
    domains: List[str] | None = None,
    urls: List[str] | None = None,
    ips: List[str] | None = None,
    hashes: List[str] | None = None,
    emails: List[str] | None = None,
    blocklist_status: str = None,
) -> List[dict[str, Any]]:
    """
    Map lists of IOCs to Threat Command API form.

    Args:
        domains (List[str] | None, optional): A list of domain IOC values to add.. Defaults to None.
        urls (List[str] | None, optional): A list of URL IOC values to add.. Defaults to None.
        ips (List[str] | None, optional): A list of IP IOC values to add.. Defaults to None.
        hashes (List[str] | None, optional): A list of hash IOC values to add.. Defaults to None.
        emails (List[str] | None, optional): A list of email IOC values to add.. Defaults to None.
        blocklist_status (str, optional): Blocklist status in case of using blocklist command. Defaults to None.

    Returns:
        List[dict[str, Any]]: Mapped list of IOCs with types.
    """
    mapped_domains = [
        {
            "Type": "Domains",
            "Value": domain,
        }
        for domain in domains or []
    ]
    mapped_hashes = [{"Type": "Hashes", "Value": hash} for hash in hashes] if hashes else []

    mapped_urls = [{"Type": "URLs" if blocklist_status else "Urls", "Value": url} for url in urls or []]
    mapped_ips = [{"Type": "IPs" if blocklist_status else "IpAddresses", "Value": ip} for ip in ips or []]
    mapped_emails = [{"Type": "EmailAddresses" if blocklist_status else "Emails", "Value": email} for email in emails or []]
    mapped_iocs = mapped_domains + mapped_urls + mapped_ips + mapped_hashes + mapped_emails
    if blocklist_status:
        for ioc in mapped_iocs:
            ioc |= {"BlocklistStatus": blocklist_status}
    return mapped_iocs


def handle_iocs(args: dict[str, Any]) -> List[str]:
    """
    Validate IOC values.

    Args:
        args (dict[str, Any]): Command arguments from XSOAR..

    Raises:
        ValueError: Insert correct domain.
        ValueError: Insert correct url.
        ValueError: Insert correct ip.
        ValueError: Insert correct hash.
        ValueError: Insert correct email.

    Returns:
        List[str]: List of IOCs.

    """
    domains = argToList(args.get("domains"))
    urls = argToList(args.get("urls"))
    ips = argToList(args.get("ips"))
    hashes = argToList(args.get("hashes"))
    emails = argToList(args.get("emails"))

    if all([not domains, not urls, not ips, not hashes, not emails]):
        raise ValueError(ReadableErrors.NO_IOCS.value)
    for iocs, ioc_type in [
        (urls, IOCType.URL),
        (ips, IOCType.IP),
        (hashes, IOCType.HASH),
        (emails, IOCType.EMAIL),
    ]:
        for ioc in iocs:
            if not re.match(pattern_and_readable_error_by_ioc_type[ioc_type][0], ioc):
                raise ValueError(pattern_and_readable_error_by_ioc_type[ioc_type][1].value.format(ioc))

    return domains + urls + ips + hashes + emails


def validate_create_source_document(args: dict[str, Any]) -> dict[str, Any]:
    """
    Validate create source document arguments.

    Args:
        args (dict[str, Any]): Command arguments from XSOAR.

    Raises:
        ValueError: Error with one of the arguments.

    Returns:
        dict[str, Any]: Updated args.
    """
    validate_argument(args=args, key_="severity", values=ArgumentValues.ALERT_IOC_AND_DOCUMENT_SEVERITY.value)
    validate_argument(args=args, key_="share", values=ArgumentValues.BOOLEAN.value)
    confidence_level = arg_to_number(args["confidence_level"])
    if not confidence_level or any([confidence_level < 0, confidence_level > 3]):
        raise ValueError(ReadableErrors.CONFIDENCE_LEVEL.value)

    handle_iocs(args=args)
    return args | {"confidence_level": confidence_level}


def multi_status_handler(
    res: dict[str, Any],
    objects: List[str],
    object_key: str,
    success_readable: str,
    fail_readable: str,
) -> List[CommandResults]:
    """
    Handle with multi status request.

    Args:
        res (dict[str, Any]): Response from the API.
        objects (List[str]): List of objects that sent with the request.
        object_key (str): Object key in the response.
        success_readable (str): Readable text for objects that succeeded.
        fail_readable (str): Readable text for objects that failed.

    Returns:
        List[CommandResults]: outputs, readable outputs and raw response for XSOAR.
    """
    succeeded = objects
    failed = []
    if (failure := res.get("failure")) and isinstance(failure, list):
        for obj in failure:
            reason = obj["failReason"]
            obj_id = obj[object_key]
            succeeded = list(set(succeeded) - {obj_id})
            failed.append(f"{obj_id} ({reason})")
    if not succeeded:
        raise ValueError(fail_readable.format((",").join(failed)))
    return remove_empty_elements(
        [
            CommandResults(readable_output=success_readable.format((",").join(succeeded))) if succeeded else None,
            CommandResults(readable_output=fail_readable.format((",").join(failed))) if failed else None,
        ]
    )


def validate_create_alert(args: dict[str, Any]):
    """
    Validator for create alerts arguments.

    Args:
        args (dict[str, Any]): Command arguments from XSOAR.

    Raises:
        ValueError: In case of wrong arguments.
    """
    scenario = args.get("scenario")
    type_ = args.get("type")
    sub_type = args.get("sub_type")

    if any(
        [
            not any([scenario, type_, sub_type]),
            all([scenario, type_, sub_type]),
            all([scenario, sub_type]) or all([scenario, type_]),
        ]
    ):
        raise ValueError(ReadableErrors.SCENARIO_TYPES.value)
    if all([type_, not sub_type]):
        raise ValueError(ReadableErrors.ALERT_SUB_TYPE.value)
    if all([not type_, sub_type]):
        raise ValueError(ReadableErrors.ALERT_TYPE.value)

    validate_argument(args=args, key_="type", values=ArgumentValues.ALERT_TYPE.value)
    validate_argument(args=args, key_="severity", values=ArgumentValues.ALERT_IOC_AND_DOCUMENT_SEVERITY.value)
    validate_argument(
        args=args,
        key_="source_network_type",
        values=ArgumentValues.ALERT_SOURCE_NETWORK.value,
    )


def validate_list_alert(args: dict[str, Any]):
    """
    Validator for list alert arguments.

    Args:
        args (dict[str, Any]): Command arguments from XSOAR.

    Raises:
        ValueError: In case of wrong arguments.
    """
    validate_argument(args=args, key_="network_type", values=ArgumentValues.ALERT_SOURCE_NETWORK.value)
    validate_argument(args=args, key_="source_type", values=ArgumentValues.SOURCE_TYPE.value)
    validate_argument(args=args, key_="alert_type", values=ArgumentValues.ALERT_TYPE.value)

    if args.get("alert_id") and argToBoolean(args["retrieve_ids_only"]):
        raise ValueError(ReadableErrors.ALERT_LIST.value)


def validate_close_alert(args: dict[str, Any]):
    """
    Validator for close alert arguments.

    Args:
        args (dict[str, Any]): Command arguments from XSOAR.

    Raises:
        ValueError: In case of wrong arguments.
    """
    validate_argument(args=args, key_="reason", values=ArgumentValues.ALERT_CLOSE_REASON.value)
    validate_argument(args=args, key_="is_hidden", values=ArgumentValues.BOOLEAN.value)
    if argToBoolean(args["is_hidden"]) and args.get("reason") != "False Positive":
        raise ValueError(ReadableErrors.IS_HIDDEN.value)

    rate = arg_to_number(args.get("rate"))

    if rate and not 0 <= rate <= 5:
        raise ValueError(ReadableErrors.RATE.value)


def validate_update_alert_blocklist(args: dict[str, Any]):
    """
    Validator for upadte alert blocklist arguments.

    Args:
        args (dict[str, Any]): Command arguments from XSOAR.

    Raises:
        ValueError: In case of wrong arguments.
    """
    handle_iocs(args=args)
    validate_argument(args=args, key_="blocklist_status", values=ArgumentValues.ALERT_BLOCKLIST.value)


def validate_assign_alert(args: dict[str, Any]):
    """
    Validator for assign alert.

    Args:
        args (dict[str, Any]): Command arguments from XSOAR.

    Raises:
        ValueError: In case of wrong arguments.
    """
    validate_argument(args=args, key_="is_mssp", values=ArgumentValues.BOOLEAN.value)


def validate_list_cve(args: dict[str, Any]):
    """
    Validator for list CVEs.

    Args:
        args (dict[str, Any]): Command arguments from XSOAR.

    Raises:
        ValueError: In case of wrong arguments.
    """
    severity_list = argToList(args.get("severity_list"))
    if severity_list and not set(severity_list).issubset(ArgumentValues.CVE_SEVERITY.value):
        raise ValueError(ReadableErrors.ARGUMENT.value.format("severity_list", ArgumentValues.CVE_SEVERITY.value))


def validate_list_account_user(args: dict[str, Any]):
    """
    Validator for list account users.

    Args:
        args (dict[str, Any]): Command arguments from XSOAR.

    Raises:
        ValueError: In case of wrong arguments.
    """
    validate_argument(args=args, key_="user_type", values=ArgumentValues.USER_TYPE.value)


def validate_alert_ioc_severity(args: dict[str, Any]):
    """
    Validator for alert IOC severity arguments.

    Args:
        args (dict[str, Any]): Command arguments from XSOAR.

    Raises:
        ValueError: In case of wrong arguments.
    """
    validate_argument(args=args, key_="severity", values=ArgumentValues.ALERT_IOC_AND_DOCUMENT_SEVERITY.value)


def validate_update_account_whitelist(args: dict[str, Any]):
    """
    Validator for update account whitelist arguments.

    Args:
        args (dict[str, Any]): Command arguments from XSOAR.

    Raises:
        ValueError: In case of wrong arguments.
    """
    validate_argument(args=args, key_="is_whitelisted", values=ArgumentValues.WHITELIST_STATUS.value)


def validate_list_ioc(args: dict[str, Any]):
    """
    Validator for list IOC arguments.

    Args:
        args (dict[str, Any]): Command arguments from XSOAR.

    Raises:
        ValueError: In case of wrong arguments.
    """
    if not args.get("last_updated_from"):
        raise ValueError(ReadableErrors.INSERT_VALUE.value.format("last_updated_from"))


def validate_search_mentions(args: dict[str, Any]):
    """
    Validator for search mentions arguments.

    Args:
        args (dict[str, Any]): Command arguments from XSOAR.

    Raises:
        ValueError: In case of wrong arguments.
    """
    if not isinstance(arg_to_number(args["page_number"]), int):
        raise ValueError(ReadableErrors.NUMBER.value)
    validate_argument(args=args, key_="source_type", values=ArgumentValues.MENTION_SOURCE_TYPE.value)
    validate_argument(args=args, key_="only_dark_web", values=ArgumentValues.BOOLEAN.value)
    validate_argument(args=args, key_="highlight_tags", values=ArgumentValues.BOOLEAN.value)


def validate_argument(args: dict[str, Any], key_: str, values: List[str]):
    """
    Validate for XSOAR input arguments.

    Args:
        args (dict[str, Any]): XSOAR arguments.
        key_ (str): The key of the argument.
        values (List[str]): Optional values.

    Raises:
        ValueError: In case that the input is wrong.
    """
    if args.get(key_) and args[key_] not in values:
        raise ValueError(ReadableErrors.ARGUMENT.value.format(key_, values))


def dict_to_lowercase(dict_: dict[str, Any]) -> dict[str, Any]:
    """
    Return a dictionary with lowercase keys.

    Args:
        dict_ (dict[str, Any]): Dictionary.

    Returns:
        dict[str, Any]: Dictionary with lowercase keys.
    """
    return {k.lower(): v for k, v in dict_.items()}


def alert_readable_outputs_handler(response: dict[str, Any]) -> dict[str, Any]:
    """
    Create readable outputs for alert.

    Args:
        response (dict[str, Any]): Alert respose

    Returns:
        dict[str, Any]: Alert readable dictionary.
    """
    return copy.deepcopy(response) | {"Tags": [tag["name"] for tag in response.get("Tags", [])]}


def arg_to_optional_bool(bool_: str | None) -> bool | None:
    """
    Returns the boolean value of the argument.

    Args:
        bool_ (str | None): Argument value.

    Returns:
        bool | None: Boolean argument.
    """
    if bool_ is None:
        return None
    return argToBoolean(bool_)


def response_obj_parser(dict_: dict[str, Any]) -> dict[str, Any]:
    """
    Parse dictionary keys to lowercase.

    Args:
        dict_ (dict[str, Any]): Dictionary to parse.

    Returns:
        dict[str, Any]: Parsed dictionary.
    """
    return {camel_case_to_underscore(k if k != "_id" else "id"): v for k, v in dict_.items()}


def minimum_severity_handler(severity: str | None) -> List[str]:
    """
    Replace minimum severity to list of the relevant severities.

    Args:
        severity (str | None): Severity value.

    Returns:
        List[str]: List of the relevant severities.
    """
    if not severity:
        return ["High", "Medium", "Low"]
    if severity == "High":
        return ["High"]
    if severity == "Medium":
        return ["High", "Medium"]
    return ["High", "Medium", "Low"]


def test_module(client: Client, params: Dict) -> str:
    """
    Test module.

    Args:
        client (Client): Threat Command client.
        params (Dict): Integration parameters.

    Returns:
        str: Output message.
    """
    try:
        if params.get("isFetch"):
            first_fetch = arg_to_datetime(params.get("first_fetch"), arg_name="First fetch timestamp")
            max_fetch = arg_to_number(params["max_fetch"])
            if not max_fetch or not isinstance(max_fetch, int) or max_fetch < 1 or max_fetch > 200:
                raise ValueError(ReadableErrors.MAX_FETCH_INVALID.value)
            if not isinstance(first_fetch, datetime):
                raise ValueError(ReadableErrors.FIRST_FETCH_NOT_EXIST.value)
        client.list_system_modules()
    except Exception as error:
        demisto.debug(str(error))
        return f"Error: {error}"
    return "ok"


def fetch_incidents(
    client: Client,
    last_run: Dict[str, Any],
    first_fetch: str,
    max_fetch: int,
    alert_types: List[str] | None,
    network_types: List[str] | None,
    alert_severities: List[str] | None,
    source_types: List[str] | None,
    fetch_csv: bool | None,
    is_closed: bool,
    fetch_attachments: bool | None,
) -> tuple[Dict[str, Any], List[dict]]:
    """
    Retrieves new alerts every interval (default is 1 minute).
    By default it's invoked by XSOAR every minute.
    It will use last_run to save the time of the last incident it processed and previous incident IDs.
    If last_run is not provided, first_fetch_time will be used to determine when to start fetching the first time.
    Args:
        client (Client): Cisco AMP client to run desired requests
        last_run (Dict[str, Any]):
            offset: Offset of the last fetched alert.
        first_fetch (str): Determines the time of when fetching has been started.
        max_fetch (int): Max number of incidents to fetch in a single run.

        alert_types (List[str], optional): Alert types to filter by.
        network_types (List[str], optional): Network types to filter by.
        alert_severities (List[str], optional): Alert severities to filter by.
        source_types (List[str], optional): Alert source types to filter by.
        fetch_csv (bool, optional): Whether to fetch CSV file if exist.
        is_closed (bool): Whether to fetch closed alerts.
        fetch_attachments (bool, optional): Whether to fetch images if exist.
    Returns:
        Tuple[Dict[str, Any], List[dict]]:
            next_run: Contains information that will be used in the next run.
            incidents: List of incidents that will be created in XSOAR.
    """
    incidents = []
    offset = None
    if (offset_time := last_run.get("time")) and (offset_id := last_run.get("last_id")):
        try:
            datetime.fromisoformat(offset_time.replace("Z", "+00:00"))
            offset = f"{offset_time}::{offset_id}"
        except ValueError:
            demisto.debug(f'Error occurred while transforming offset time "{offset_time}" from last run.')
            offset = None

    list_response = client.list_alert(
        offset=offset,
        limit=max_fetch,
        last_updated_from=first_fetch,
        alert_type=alert_types,
        network_type=network_types,
        severity=alert_severities,
        source_type=source_types,
        is_closed=is_closed,
    )
    if not list_response.get("content"):
        demisto.debug(f'Alerts not found with the provided parameters and with the offset "{offset}".')
        return last_run, []

    alert_ids = [alert["_id"] for alert in list_response["content"]]
    alert_ids_list = ", ".join(alert_ids)
    demisto.debug(f'List of alert IDs "{alert_ids_list}" found with the provided parameters and with the offset "{offset}".')
    for alert_id in alert_ids:
        alert_details = client.get_alert(alert_id=alert_id)
        incident = client.parser.alert_fetch_parser(alert_details)
        incident["fetch_csv"] = fetch_csv
        incident["fetch_attachments"] = fetch_attachments
        incidents.append(client.parser.parse_incident(alert=incident))

    offset_date = list_response["content"][-1].get("updateDate")
    offset_id = list_response["content"][-1].get("_id")
    next_run = {"time": offset_date, "last_id": offset_id}
    return next_run, incidents


def main() -> None:
    params: dict[str, Any] = demisto.params()
    args: dict[str, Any] = demisto.args()
    base_url = params["base_url"]
    account_id = dict_safe_get(params, ["credentials", "identifier"])
    api_key = dict_safe_get(params, ["credentials", "password"])
    mssp_sub_account = params.get("mssp_sub_account")
    reliability = params.get("integrationReliability", DBotScoreReliability.C)
    verify_certificate: bool = not params.get("insecure", False)
    proxy = params.get("proxy", False)
    execution_metrics = ExecutionMetrics()

    if DBotScoreReliability.is_valid_type(reliability):
        reliability = DBotScoreReliability.get_dbot_score_reliability_from_str(reliability)
    else:
        raise ValueError("Please provide a valid value for the Source Reliability parameter.")

    command = demisto.command()
    demisto.debug(f"The command being called is {command}.")
    commands: Dict[str, Callable] = {
        "threat-command-cyber-term-list": list_cyber_term_command,
        "threat-command-cyber-term-cve-list": list_cyber_term_cve_command,
        "threat-command-cyber-term-ioc-list": list_cyber_term_ioc_command,
        "threat-command-source-list": list_source_command,
        "threat-command-source-document-create": create_source_document_command,
        "threat-command-source-document-delete": delete_source_document_command,
        "threat-command-source-document-ioc-create": create_source_document_ioc_command,
        "threat-command-ioc-tags-add": add_tags_ioc_command,
        "threat-command-ioc-severity-update": update_ioc_severity_command,
        "threat-command-ioc-comment-add": add_ioc_comment_command,
        "threat-command-enrichment-quota-usage": usage_quota_enrichment_command,
        "threat-command-account-whitelist-update": update_account_whitelist_command,
        "threat-command-account-whitelist-remove": remove_account_whitelist_command,
        "threat-command-ioc-blocklist-add": add_ioc_blocklist_command,
        "threat-command-ioc-blocklist-remove": remove_ioc_blocklist_command,
        "threat-command-alert-list": list_alert_handler_command,
        "threat-command-alert-takedown-request": takedown_alert_command,
        "threat-command-alert-takedown-request-status-get": get_takedown_alert_command,
        "threat-command-alert-create": create_alert_command,
        "threat-command-alert-close": close_alert_command,
        "threat-command-alert-severity-update": update_alert_severity_command,
        "threat-command-alert-blocklist-get": get_alert_blocklist_status_command,
        "threat-command-alert-blocklist-update": update_alert_blocklist_command,
        "threat-command-alert-ioc-report": report_alert_ioc_command,
        "threat-command-alert-assign": assign_alert_command,
        "threat-command-alert-unassign": unassign_alert_command,
        "threat-command-alert-reopen": reopen_alert_command,
        "threat-command-alert-tag-add": tag_alert_command,
        "threat-command-alert-tag-remove": untag_alert_command,
        "threat-command-alert-send-mail": send_mail_alert_command,
        "threat-command-alert-analyst-ask": analyst_ask_alert_command,
        "threat-command-alert-analyst-conversation-list": list_alert_conversation_command,
        "threat-command-alert-activity-log-get": list_alert_activity_command,
        "threat-command-alert-csv-get": get_alert_csv_command,
        "threat-command-alert-note-add": add_alert_note_command,
        "threat-command-alert-image-list": list_alert_image_command,
        "threat-command-cve-list": list_cve_command,
        "threat-command-cve-add": add_cve_command,
        "threat-command-cve-delete": delete_cve_command,
        "threat-command-asset-add": add_asset_command,
        "threat-command-asset-list": list_assets_command,
        "threat-command-asset-type-list": list_asset_types_command,
        "threat-command-asset-delete": delete_asset_command,
        "threat-command-account-system-modules-list": list_system_modules_command,
        "threat-command-mention-search": search_mention_command,
        "threat-command-mssp-customer-list": list_mssp_customer_command,
        "threat-command-mssp-user-list": list_mssp_user_command,
        "threat-command-account-user-list": list_account_user_command,
        "threat-command-alert-type-list": list_alert_type_command,
        "threat-command-alert-source-type-list": list_alert_source_type_command,
        "threat-command-alert-scenario-list": list_alert_scenario_command,
    }
    polling_commands = {
        "threat-command-ioc-search": search_ioc_handler_command,
        "file": file_command,
        "ip": ip_command,
        "url": url_command,
        "domain": domain_command,
    }

    try:
        client: Client = Client(
            base_url=base_url,
            account_id=account_id,
            api_key=api_key,
            mssp_sub_account=mssp_sub_account,
            reliability=reliability,
            verify=verify_certificate,
            proxy=proxy,
        )
        if command == "test-module":
            return_results(test_module(client, params))
        elif command in polling_commands:
            return_results(polling_commands[command](args, client, execution_metrics))
        elif command in commands:
            return_results(commands[command](client, args))
        elif command == "fetch-incidents":
            first_fetch = arg_to_datetime(params.get("first_fetch"))
            max_fetch = arg_to_number(params["max_fetch"])
            if isinstance(max_fetch, int) and max_fetch > 200:
                demisto.debug(
                    f"The max fetch value is {max_fetch}, which is greater than the maximum allowed value "
                    "of 200. Setting it to 200."
                )
                max_fetch = 200
            alert_types = argToList(params.get("alert_types"))
            network_types = argToList(params.get("network_types"))
            alert_severities = minimum_severity_handler(params.get("alert_severity"))
            source_types = argToList(params.get("source_types"))
            is_closed = argToBoolean(params["fetch_closed_incidents"])
            fetch_csv = argToBoolean(params["fetch_csv"])
            fetch_attachments = argToBoolean(params["fetch_attachments"])
            if not max_fetch or max_fetch < 1:
                raise ValueError("max_fetch must be a positive integer.")

            if not isinstance(first_fetch, datetime):
                raise ValueError(ReadableErrors.FIRST_FETCH_NOT_EXIST.value)

            first_fetch_time = first_fetch.strftime(ISO_8601_FORMAT)

            last_run = demisto.getLastRun()
            next_run, incidents = fetch_incidents(
                client=client,
                last_run=last_run,
                first_fetch=first_fetch_time,
                max_fetch=max_fetch,
                alert_types=alert_types,
                network_types=network_types,
                alert_severities=alert_severities,
                source_types=source_types,
                is_closed=is_closed,
                fetch_csv=fetch_csv,
                fetch_attachments=fetch_attachments,
            )
            demisto.info(f"Fetched {len(incidents)} new incidents.")
            demisto.setLastRun(next_run)
            demisto.incidents(incidents)
        else:
            raise NotImplementedError(f"{command} command is not implemented.")

    except Exception as e:
        return_error(str(e))


if __name__ in ["__main__", "builtin", "builtins"]:
    main()