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
| ID | rapid7_threat_command |
|---|---|
| Provider | Rapid7 |
| Category | Network Security |
| From Version | 6.8.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix 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,
UkraineAerospace/Defense,
Government,
ManufacturingThe 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,
PolicyTag59490cd818a3b902664b4ed7 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
#### Context Example
```json
{
"ThreatCommand": {
"SystemModule": [
{
"module_name": "discovery",
"status": true
},
{
"module_name": "remediation",
"status": true
},
{
"module_name": "ioc",
"status": true
},
{
"module_name": "virtualappliance",
"status": true
},
{
"module_name": "investigationpage",
"status": true
},
{
"module_name": "threatlibrary",
"status": false
},
{
"module_name": "intellifind",
"status": true
},
{
"module_name": "cve",
"status": true
}
]
}
}
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 o2023-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 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 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 incidentsfirst_fetch— First fetch timestamp.max_fetch— Maximum incidents per fetch (required)alert_types— Alert types to fetch as incidentsnetwork_types— Network types to fetch as incidentsalert_severity— Minimum Alert Severity Levelsource_types— Source types to filter alerts byfetch_closed_incidents— Fetch closed alertsfetch_csv— Include CSV files of alertsfetch_attachments— Include attachments of alertsmssp_sub_account— Sub-account ID (for MSSP accounts).incidentType— Incident typeincidentFetchInterval— Incidents Fetch Intervalproxy— Use system proxy settingsinsecure— Trust any certificate (not secure)
Commands (56)
-
domainChecks the reputation of a domain.
-
fileRuns reputation on files.
-
ipChecks the reputation of an IP address.
-
threat-command-account-system-modules-listList the system modules of your account.
-
threat-command-account-user-listList the users in your account. Mainly used to assign alerts.
-
threat-command-account-whitelist-removeReverts 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-updateYou 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-getGet alert activity log.
-
threat-command-alert-analyst-askSend 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-listGet alert's analyst response.
-
threat-command-alert-assignAssign 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-getGet alert's blocklist status.
-
threat-command-alert-blocklist-updateChange selected IOCs blocklist status.
-
threat-command-alert-closeClose alert.
-
threat-command-alert-createCreate a new alert. You have to insert scenario or type and sub_type.
-
threat-command-alert-csv-getGet alert's CSV file in case of credentials leakage or leaked credit cards alerts.
-
threat-command-alert-image-listList alert images by ID.
-
threat-command-alert-ioc-reportReport 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-listGet a list of alerts with all details.
-
threat-command-alert-note-addAdd 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-reopenReopen alert.
-
threat-command-alert-scenario-listList alert scenarios. They are mainly used to add manual alerts.
-
threat-command-alert-send-mailSend mail with the alert details and a question.
-
threat-command-alert-severity-updateChange the alert's severity. Changing the severity level of alerts can help to prioritize alert management.
-
threat-command-alert-source-type-listList alert source types. They are mainly used to add manual alerts.
-
threat-command-alert-tag-addAdds 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-removeRemoves a tag from the alert.
-
threat-command-alert-takedown-requestSend 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-getGet the alert's takedown status.
-
threat-command-alert-type-listList alert types and sub-types. They are mainly used to add manual alerts.
-
threat-command-alert-unassignUnassign an alert from all users.
-
threat-command-asset-addAdd assets by type and value. Assets include any company resource that could lead to a potential security threat.
-
threat-command-asset-deleteDelete asset by type and value.
-
threat-command-asset-listGet account assets grouped by asset type.
-
threat-command-asset-type-listGet all asset types. Mainly used to add or delete assets.
-
threat-command-cve-addAdd CVEs to account.
-
threat-command-cve-deleteDelete CVEs from account.
-
threat-command-cve-listGet CVE's list from account.
-
threat-command-cyber-term-cve-listList cyber term CVEs by cyber term ID.
-
threat-command-cyber-term-ioc-listList cyber term IOCs by cyber term ID.
-
threat-command-cyber-term-listList cyber terms by filter.
-
threat-command-enrichment-quota-usageGets the current API enrichment credits ("quota") usage for the requester account.
-
threat-command-ioc-blocklist-addAdds 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-removeRemoves 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-addAdds comments to IOCs. At least one IOC is required.
-
threat-command-ioc-searchGets 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-updateChanges the severity of existing IOCs for the requester account (overrides the system severity). At least one IOC is required.
-
threat-command-ioc-tags-addAdds 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-searchSearch for strings in the scrapes database.
-
threat-command-mssp-customer-listGet all Managed Security Service Provider's (MSSP) sub-accounts.
-
threat-command-mssp-user-listGet the details of the MSSPs users (In case you are an MSSP account).
-
threat-command-source-document-createAdds a new IOC source document. At least one IOC is required.
-
threat-command-source-document-deleteDeletes an existing IOC source document.
-
threat-command-source-document-ioc-createCreate new IOCs to existing IOC source documents. At least one IOC is required.
-
threat-command-source-listGets lists of IOC document sources.
-
urlChecks 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()