GoogleThreatIntelligenceDTMAlerts

This integration allows the creation of incidents based on DTM Alerts from Google Threat Intelligence.

Data Enrichment & Threat Intelligence · GoogleThreatIntelligence

Details

IDGoogleThreatIntelligenceDTMAlerts
ProviderGoogle
CategoryData Enrichment & Threat Intelligence
From Version6.10.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

Google Threat Intelligence - DTM Alerts

This integration allows the creation of incidents based on DTM Alerts from Google Threat Intelligence.

Configure Google Threat Intelligence - DTM Alerts in Cortex

Parameter Description Required
API Key   True
Fetch incidents   False
Max Fetch Maximum number of Alerts to fetch each time. Maximum value is 100. False
First Fetch Time The date or relative timestamp from which to begin fetching Alerts.

Supported formats: 2 minutes, 2 hours, 2 days, 2 weeks, 2 months, 2 years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ.

For example: 01 May 2025, 01 May 2025 04:45:33, 2025-05-17T14:05:44Z.
False
Mirroring Direction The mirroring direction in which to mirror the details. You can mirror “Outgoing” (from XSOAR to GTI) direction for DTM Alerts. Cortex XSOAR only parameter. False
Alert Type Fetch Alerts by the specified alert types. False
Alert Monitor ID Fetch Alerts by the specified monitor IDs. False
Alert Status Fetch Alerts by the specified status. False
Alert Severity Fetch Alerts by the specified severity. False
Alert Tags Fetch Alerts by the specified tags. False
Alert Match Value Fetch Alerts by specified match value. False
Alert mscore Fetch Alerts with mscore greater than or equal to the given value.

Note: Valid range is 0 to 100.
False
Alert Search Search Alerts and triggering documents using a Lucene query with text values joined by AND/OR. False
Use system proxy settings   False
Trust any certificate (not secure)   False
Incident type    

Acquiring your API key

Your API key can be found in your GoogleThreatIntelligence account user menu, clicking on your avatar:

How to get api key in GoogleThreatIntelligence

Your API key carries all your privileges, so keep it secure and don’t share it with anyone.

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.

gti-dtm-alert-list


Search the DTM Alerts with provided filter arguments.

Base Command

gti-dtm-alert-list

Input

Argument Name Description Required
start_time Start time of the time range to list alerts.

Supported formats: 2 minutes, 2 hours, 2 days, 2 weeks, 2 months, 2 years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ.

For example: 01 May 2025, 01 Mar 2025 04:45:33, 2025-04-17T14:05:44Z.
Optional
end_time End time of the time range to list alerts.

Supported formats: 2 minutes, 2 hours, 2 days, 2 weeks, 2 months, 2 years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ.

For example: 01 May 2025, 01 Mar 2025 04:45:33, 2025-04-17T14:05:44Z.
Optional
order Filter alerts by the provided sort order. Possible values are: Asc, Desc. Default is Desc. Optional
sort Filter alerts by the provided sort field. Possible values are: Created At, Updated At, Monitor ID, ID. Default is Created At. Optional
page_size Specify the desired page size for the request. Maximum value is 25. Default is 10. Optional
monitor_id Filter alerts by monitor IDs. Supports comma-separated values. Optional
alert_type Filters alerts by their alert type. Supports comma-separated values. Possible values are: Compromised Credentials, Domain Discovery, Forum Post, Message, Paste, Shop Listing, Tweet, Web Content. Optional
tags Filter alerts by tags value. Supports comma-separated values. Optional
status Filter alerts by the provided status. Supports comma-separated values. Possible values are: New, Read, In Progress, Escalated, Closed, No Action Required, Duplicate, Not Relevant, Tracked External. Optional
severity Filter alerts by severity. Supports comma-separated values. Possible values are: Low, Medium, High. Optional
mscore_gte Filter alerts with mscore greater than or equal to the given value.

Note: Valid range is 0 to 100.
Optional
include_more_details If yes, doc, labels, and topics are returned in the context data. Possible values are: Yes, No. Default is Yes. Optional
include_monitor_name If yes, then the monitor’s name that created the alert is returned in the alert response body. Possible values are: Yes, No. Default is No. Optional
has_analysis If yes, then only alerts that have analysis are returned. An alert has analysis if it has either analysis text or analysis file attachments. Possible values are: Yes, No. Optional
search Filter alert and triggering document contents using a simple Lucene query string with one or more text values separated by AND or OR. Optional
match_value Filter alerts by the given match value. Supports comma-separated values. Optional

Context Output

Path Type Description
GoogleThreatIntelligenceDTMAlerts.Alerts.id String Unique identifier for the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.monitor_id String Identifier of the monitoring source that generated the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.__id String Unique document ID associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.__type String Type of document associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.body String Full content or message body of the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.channel_id String ID of the channel where the alert was observed.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.channel_info.description String Description of the channel where the alert was detected.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.channel_url String URL of the detected channel.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.invite_url String Invite link of the detected channel, if available.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.messenger.id String Identifier of the messenger platform linked to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.messenger.name String Name of the messenger platform.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.name String Name of the channel where the content was found.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.ingested Date Date and time when the document was ingested into the system.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.message_id String Identifier of the specific message triggering the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.messenger.id String Messenger platform ID associated with the message.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.messenger.name String Name of the messenger platform associated with the message.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.avatar_file.hashes.sha256 String SHA-256 hash of the sender’s avatar file.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.avatar_file.mime_type String MIME type of the sender’s avatar file.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.identity.first_name String First name of the sender.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.identity.last_name String Last name of the sender.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.identity.name String Full name of the sender.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.telegram.name String Telegram username of the sender.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.telegram.user_id Number Telegram user ID of the sender.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.source String Source of the document or content triggering the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.timestamp Date Timestamp when the message or document was created.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.id String Unique identifier of the label assigned to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.classifier String Classifier name used for label assignment.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.version String Version of the classifier or labeling process.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.label String Name of the label assigned to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.confidence Number Confidence score of the assigned label.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.element_path String Path of the element where the label was applied.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.id String Unique identifier of the extracted topic.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.type String Type of the extracted topic.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.value String Value of the extracted topic.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.extractor String Name of the topic extraction tool.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.extractor_version String Version of the topic extractor used.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.entity_locations.element_path String Path of the element where the entity was detected.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.entity_locations.offsets Number Character offsets of the detected entity in the document.
GoogleThreatIntelligenceDTMAlerts.Alerts.topic_matches.topic_id String Identifier of the matched topic.
GoogleThreatIntelligenceDTMAlerts.Alerts.topic_matches.value String Matched value for the topic.
GoogleThreatIntelligenceDTMAlerts.Alerts.label_matches List List of labels matched for the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc_matches.match_path String Path within the document where a match occurred.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc_matches.locations.offsets Number Offset positions of the document match.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc_matches.locations.value String Value of the matched document content.
GoogleThreatIntelligenceDTMAlerts.Alerts.tags List Tags associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.created_at Date Date and time when the alert was created.
GoogleThreatIntelligenceDTMAlerts.Alerts.updated_at Date Date and time when the alert was last updated.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels_url String URL to fetch labels associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics_url String URL to fetch topics associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc_url String URL of the original document related to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.status String Current status of the alert (e.g., open, closed, triaged).
GoogleThreatIntelligenceDTMAlerts.Alerts.alert_type String Type or category of the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.alert_summary String Summary of the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.title String Title of the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.email_sent_at String Timestamp when the alert email was sent.
GoogleThreatIntelligenceDTMAlerts.Alerts.indicator_mscore Number Malicious score of the indicator related to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.severity String Severity level of the alert (e.g., low, medium, high).
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence Number Confidence score of the alert detection.
GoogleThreatIntelligenceDTMAlerts.Alerts.aggregated_under_id String ID under which the alert has been aggregated.
GoogleThreatIntelligenceDTMAlerts.Alerts.monitor_name String Name of the monitoring source that generated the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.analysis String Analysis report or details associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.has_analysis Boolean Indicates whether the alert has an associated analysis.
GoogleThreatIntelligenceDTMAlerts.Alerts.ai_doc_summary String AI-generated summary of the document related to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.similarity_score Number Similarity score between this alert and related alerts.
GoogleThreatIntelligenceDTMAlerts.Alerts.severity_reasoning.rule String Rule used to determine the severity of the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.version String Version of the confidence reasoning model.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.response_count Number Number of responses contributing to confidence reasoning.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.malicious_count Number Number of malicious detections contributing to confidence.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.benign_count Number Number of benign detections contributing to confidence.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.confidence_count Number Total number of samples considered for confidence calculation.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.explanation String Explanation behind the confidence score.
GoogleThreatIntelligenceDTMAlerts.Alerts.ignore Boolean Indicates if the alert should be ignored.
GoogleThreatIntelligenceDTMAlerts.Alerts.monitor_version Number Version of the monitoring source generating the alert.

Command example

!gti-dtm-alert-list alert_type=Message include_monitor_name=Yes include_more_details=Yes mscore_gte=11 order=Desc page_size=2 search=social severity=Low sort="Created At" tags=attempt

Context Example

{
    "GoogleThreatIntelligenceDTMAlerts": {
        "Alerts": [
            {
                "aggregated_under_id": "dummyaggregated_id_01",
                "ai_doc_summary": "This message advertises a service that provides fraudulent Google verification badges for any account. \n",
                "alert_summary": "Google verification badges for any account of the gmail and cloud.",
                "alert_type": "Message",
                "confidence": 0.20271267571752816,
                "confidence_reasoning": {
                    "benign_count": 0,
                    "malicious_count": 0,
                    "response_count": 0,
                    "version": ""
                },
                "created_at": "2025-05-21T11:28:02.646Z",
                "doc": {
                    "__id": "dummy_id_01",
                    "__type": "message",
                    "body": "dummy body for DTM Alerts",
                    "channel": {
                        "channel_id": "channeldummy",
                        "channel_info": {
                            "description": "Surge Market"
                        },
                        "channel_url": "dummyurl",
                        "invite_url": "dummyurl",
                        "messenger": {
                            "id": "Googlechat",
                            "name": "Googlechat"
                        },
                        "name": "social"
                    },
                    "ingested": "2025-05-21T11:27:45Z",
                    "message_id": "dummymessageid01",
                    "messenger": {
                        "id": "Googlechat",
                        "name": "Googlechat"
                    },
                    "sender": {
                        "identity": {
                            "first_name": "Crome Bot",
                            "name": "Crome Bot "
                        },
                        "googlechat": {
                            "name": "gmail",
                            "user_id": 220903062
                        }
                    },
                    "source": "googlw",
                    "timestamp": "2025-05-21T11:27:42Z"
                },
                "doc_matches": [
                    {
                        "locations": [
                            {
                                "offsets": [
                                    688,
                                    692
                                ],
                                "value": "full"
                            },
                            {
                                "offsets": [
                                    693,
                                    699
                                ],
                                "value": "access"
                            }
                        ],
                        "match_path": "body"
                    }
                ],
                "doc_url": "https://www.virustotal.com/v4/dtm/docs/message/dummydocurl01",
                "email_sent_at": "",
                "has_analysis": false,
                "id": "dummy_0000",
                "ignore": false,
                "indicator_mscore": 11,
                "tags": ["attempt","Test"],
                "labels": [
                    {
                        "classifier": "classifier-content",
                        "confidence": 100,
                        "element_path": "body",
                        "id": "dummy_label_id",
                        "label": "prose",
                        "version": "dummy_version"
                    }
                ],
                "labels_url": "https://www.virustotal.com/v4/dtm/docs/message/dummydocurl01/labels",
                "monitor_id": "dummy_monitor_id",
                "monitor_name": "Initial Access Broker",
                "monitor_version": 1,
                "severity": "low",
                "severity_reasoning": {
                    "rule": ""
                },
                "similarity_score": 0.9906103,
                "status": "read",
                "title": "Found topic \"google\" posted by actor \"sevenbump\" on channel \"social\"",
                "topic_matches": [
                    {
                        "offsets": [
                            0,
                            4
                        ],
                        "term": "google",
                        "topic_id": "dummy_topicid_01",
                        "value": "google"
                    },
                    {
                        "topic_id": "dummy_topicid_02",
                        "value": "message"
                    }
                ],
                "topics": [
                    {
                        "confidence": 99,
                        "entity_locations": [
                            {
                                "element_path": "body",
                                "offsets": [
                                    488,
                                    491
                                ]
                            }
                        ],
                        "extractor": "analysis of the message",
                        "extractor_version": "4-0-2",
                        "id": "dummy_topicid_01",
                        "type": "organization",
                        "value": "social"
                    },
                    {
                        "confidence": 94,
                        "entity_locations": [
                            {
                                "element_path": "body",
                                "offsets": [
                                    701,
                                    704
                                ]
                            }
                        ],
                        "extractor": "analysis-pipeline",
                        "extractor_version": "4-0-2",
                        "id": "dummy_topicid_02",
                        "type": "product",
                        "value": "social"
                    }
                ],
                "topics_url": "https://www.virustotal.com/v4/dtm/docs/message/dummydocurl02/topics",
                "updated_at": "2025-05-22T07:09:51.257Z"
            },
            {
                "aggregated_under_id": "dummy_aggregated_under_id_02",
                "ai_doc_summary": "This message advertises a service that offers unauthorized google account.\n",
                "alert_summary": "Google account verification service cromeam Stand out your way use any name any username any profile pic or none at all.",
                "alert_type": "Message",
                "confidence": 0.20271267571752816,
                "confidence_reasoning": {
                    "benign_count": 0,
                    "malicious_count": 0,
                    "response_count": 0,
                    "version": ""
                },
                "created_at": "2025-05-21T10:19:04.241Z",
                "doc": {
                    "__id": "dummy_doc_id_02",
                    "__type": "message",
                    "body": "this is body of message",
                    "channel": {
                        "channel_id": "-1001097206146",
                        "channel_info": {
                            "description": "Surge Market"
                        },
                        "channel_url": "https://dummyurl.com",
                        "invite_url": "https://dummyurl.com",
                        "messenger": {
                            "id": "googlechat",
                            "name": "Googlechat"
                        },
                        "name": "social"
                    },
                    "ingested": "2025-05-21T10:19:00Z",
                    "message_id": "dummy_message_id_02",
                    "messenger": {
                        "id": "googlechat",
                        "name": "Googlechat"
                    },
                    "sender": {
                        "identity": {
                            "first_name": "Crome Bot",
                            "name": "Crome Bot "
                        },
                        "telegram": {
                            "name": "sevenbump",
                            "user_id": 220903062
                        }
                    },
                    "source": "google",
                    "timestamp": "2025-05-21T10:18:55Z"
                },
                "doc_matches": [
                    {
                        "locations": [
                            {
                                "offsets": [
                                    688,
                                    692
                                ],
                                "value": "full"
                            },
                            {
                                "offsets": [
                                    693,
                                    699
                                ],
                                "value": "access"
                            }
                        ],
                        "match_path": "body"
                    }
                ],
                "doc_url": "https://www.virustotal.com/v4/dtm/docs/message/dummydocurl03",
                "email_sent_at": "",
                "has_analysis": false,
                "id": "dummy_0001",
                "ignore": false,
                "indicator_mscore": 11,
                "tags": ["attempt"],
                "labels": [
                    {
                        "classifier": "classifier-content",
                        "confidence": 100,
                        "element_path": "body",
                        "id": "dummyid03",
                        "label": "prose",
                        "version": "dummyversion03"
                    }
                ],
                "labels_url": "https://www.virustotal.com/v4/dtm/docs/message/dummydocurl03/labels",
                "monitor_id": "dummy_monitor_id",
                "monitor_name": "Initial Access Broker",
                "monitor_version": 1,
                "severity": "low",
                "severity_reasoning": {
                    "rule": ""
                },
                "similarity_score": 0.9906103,
                "status": "read",
                "title": "Found topic \"Google\" posted by actor \"sevenbump\" on Google channel \"social\"",
                "topic_matches": [
                    {
                        "offsets": [
                            0,
                            4
                        ],
                        "term": "dummyterm03",
                        "topic_id": "dummy_topic_01",
                        "value": "dummyvalue_03"
                    },
                    {
                        "topic_id": "dummay_topic_02",
                        "value": "message"
                    }
                ],
                "topics": [
                    {
                        "entity_locations": [
                            {
                                "element_path": "channel.name",
                                "offsets": [
                                    0,
                                    17
                                ]
                            }
                        ],
                        "extractor": "dtm-ma",
                        "extractor_version": "1.0.595",
                        "id": "dummy_topic_01",
                        "type": "name",
                        "value": "social"
                    },
                    {
                        "entity_locations": [
                            {
                                "element_path": "messenger.name",
                                "offsets": [
                                    0,
                                    8
                                ]
                            },
                            {
                                "element_path": "channel.messenger.name",
                                "offsets": [
                                    0,
                                    8
                                ]
                            }
                        ],
                        "extractor": "dtm-ma",
                        "extractor_version": "1.0.595",
                        "id": "dummay_topic_02",
                        "type": "service_name",
                        "value": "Googlechat"
                    }],
                "topics_url": "https://www.virustotal.com/v4/dtm/docs/message/dummy0001/topics",
                "updated_at": "2025-05-22T07:09:51.257Z"
            }
        ]
    }
}

Human Readable Output

DTM Alerts

Alert ID Title Alert Summary Alert Type Severity Status Monitor ID Monitor Name Indicator Score Created At Updated At Tags
dummy_0000 Found topic “google” posted by actor “sevenbump” on channel “social” This message advertises a service that provides fraudulent Google verification badges for any account.
Message Low Read dummy_monitor_id Initial Access Broker 11 2025-05-21T11:28:02.646Z 2025-05-22T07:09:51.257Z attempt,
Test
dummy_0001 Found topic “Google” posted by actor “sevenbump” on Google channel “social” This message advertises a service that offers unauthorized google account.
Message Low Read dummy_monitor_id Initial Access Broker 11 2025-05-21T10:19:04.241Z 2025-05-22T07:09:51.257Z attempt

gti-dtm-alert-get


Get a particular DTM Alert by ID.

Base Command

gti-dtm-alert-get

Input

Argument Name Description Required
alert_id Specify ID of the alert.

Note: Use gti-dtm-alert-list to retrive the Alert ID.
Required
include_more_details If yes, doc, labels, and topics are returned in the context data. Possible values are: Yes, No. Default is Yes. Optional
sanitize If yes, any HTML content in the alert is sanitized to ensure it does not contain malicious tags. Possible values are: Yes, No. Optional
truncate Specify whether to truncate document fields to the given length.

Note: A Unicode ellipsis (\x2026) is used to indicate truncation.
Optional

Context Output

Path Type Description
GoogleThreatIntelligenceDTMAlerts.Alerts.id String Unique identifier for the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.monitor_id String Identifier of the monitoring source that generated the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.__id String Unique document ID associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.__type String Type of document associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.body String Full content or message body of the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.channel_id String ID of the channel where the alert was observed.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.channel_info.description String Description of the channel where the alert was detected.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.channel_url String URL of the detected channel.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.invite_url String Invite link of the detected channel, if available.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.messenger.id String Identifier of the messenger platform linked to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.messenger.name String Name of the messenger platform.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.name String Name of the channel where the content was found.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.ingested Date Date and time when the document was ingested into the system.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.message_id String Identifier of the specific message triggering the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.messenger.id String Messenger platform ID associated with the message.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.messenger.name String Name of the messenger platform associated with the message.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.avatar_file.hashes.sha256 String SHA-256 hash of the sender’s avatar file.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.avatar_file.mime_type String MIME type of the sender’s avatar file.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.identity.first_name String First name of the sender.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.identity.last_name String Last name of the sender.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.identity.name String Full name of the sender.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.telegram.name String Telegram username of the sender.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.telegram.user_id Number Telegram user ID of the sender.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.source String Source of the document or content triggering the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.timestamp Date Timestamp when the message or document was created.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.id String Unique identifier of the label assigned to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.classifier String Classifier name used for label assignment.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.version String Version of the classifier or labeling process.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.label String Name of the label assigned to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.confidence Number Confidence score of the assigned label.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.element_path String Path of the element where the label was applied.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.id String Unique identifier of the extracted topic.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.type String Type of the extracted topic.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.value String Value of the extracted topic.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.extractor String Name of the topic extraction tool.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.extractor_version String Version of the topic extractor used.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.entity_locations.element_path String Path of the element where the entity was detected.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.entity_locations.offsets Number Character offsets of the detected entity in the document.
GoogleThreatIntelligenceDTMAlerts.Alerts.topic_matches.topic_id String Identifier of the matched topic.
GoogleThreatIntelligenceDTMAlerts.Alerts.topic_matches.value String Matched value for the topic.
GoogleThreatIntelligenceDTMAlerts.Alerts.label_matches List List of labels matched for the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc_matches.match_path String Path within the document where a match occurred.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc_matches.locations.offsets Number Offset positions of the document match.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc_matches.locations.value String Value of the matched document content.
GoogleThreatIntelligenceDTMAlerts.Alerts.tags List Tags associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.created_at Date Date and time when the alert was created.
GoogleThreatIntelligenceDTMAlerts.Alerts.updated_at Date Date and time when the alert was last updated.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels_url String URL to fetch labels associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics_url String URL to fetch topics associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc_url String URL of the original document related to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.status String Current status of the alert (e.g., open, closed, triaged).
GoogleThreatIntelligenceDTMAlerts.Alerts.alert_type String Type or category of the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.alert_summary String Summary of the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.title String Title of the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.email_sent_at String Timestamp when the alert email was sent.
GoogleThreatIntelligenceDTMAlerts.Alerts.indicator_mscore Number Malicious score of the indicator related to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.severity String Severity level of the alert (e.g., low, medium, high).
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence Number Confidence score of the alert detection.
GoogleThreatIntelligenceDTMAlerts.Alerts.aggregated_under_id String ID under which the alert has been aggregated.
GoogleThreatIntelligenceDTMAlerts.Alerts.has_analysis Boolean Indicates whether the alert has an associated analysis.
GoogleThreatIntelligenceDTMAlerts.Alerts.ai_doc_summary String AI-generated summary of the document related to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.similarity_score Number Similarity score between this alert and related alerts.
GoogleThreatIntelligenceDTMAlerts.Alerts.severity_reasoning.rule String Rule used to determine the severity of the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.version String Version of the confidence reasoning model.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.response_count Number Number of responses contributing to confidence reasoning.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.malicious_count Number Number of malicious detections contributing to confidence.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.benign_count Number Number of benign detections contributing to confidence.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.confidence_count Number Total number of samples considered for confidence calculation.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.explanation String Explanation behind the confidence score.
GoogleThreatIntelligenceDTMAlerts.Alerts.ignore Boolean Indicates if the alert should be ignored.
GoogleThreatIntelligenceDTMAlerts.Alerts.monitor_version Number Version of the monitoring source generating the alert.

Command example

!gti-dtm-alert-get alert_id=dummy_alert_001

Context Example

{
    "GoogleThreatIntelligenceDTMAlerts": {
        "Alerts": {
            "aggregated_under_id": "dummy_alert_001",
            "ai_doc_summary": "This advertisement details a sophisticated phishing-as-a-service platform verified email spoofing capabilities",
            "alert_summary": "Angel Mailer the best possible solution for all your mailing needs Our main features 1 1 Verified Mails with Checkmark on Google",
            "alert_type": "Message",
            "confidence": 0.5404703550433493,
            "confidence_reasoning": {
                "benign_count": 0,
                "malicious_count": 0,
                "response_count": 0,
                "version": ""
            },
            "created_at": "2025-08-19T09:29:31.827Z",
            "doc": {
                "__id": "dummy",
                "__type": "message",
                "body": "Welcome to Angel Mailer, the best possible solution for all your mailing needs. \n\nOur main features:\n\n💎 1:1 Verified Mails with Checkmark on googl/AOL\n\n A lot of templates with a choice of spoof.",
                "channel": {
                    "channel_id": "dummy",
                    "channel_info": {
                        "description": "chasingchicken"
                    },
                    "channel_url": "DUMMY",
                    "invite_url": "DUMMY",
                    "messenger": {
                        "id": "google",
                        "name": "Google"
                    },
                    "name": "dummy"
                },
                "ingested": "2025-08-19T08:43:20Z",
                "message_id": "dummy",
                "messenger": {
                    "id": "google",
                    "name": "Google"
                },
                "parts": [
                    {
                        "content_type": "video/mp4",
                        "filename": "angelmailerready.mp4"
                    }
                ],
                "sender": {
                    "identity": {
                        "first_name": "dummy_xyz",
                        "name": "dummy_xyz"
                    },
                    "google": {
                        "user_id": 157338048
                    }
                },
                "source": "Google",
                "timestamp": "2025-08-19T08:43:16Z"
            },
            "doc_matches": [
                {
                    "locations": [
                        {
                            "offsets": [
                                395,
                                399
                            ],
                            "value": "full"
                        }
                    ],
                    "match_path": "body"
                }
            ],
            "doc_url": "https://www.virustotal.com/v4/dtm/docs/message/dummy",
            "email_sent_at": "",
            "has_analysis": false,
            "id": "dummy_alert_001",
            "ignore": false,
            "indicator_mscore": 92,
            "labels": [
                {
                    "classifier": "classifier-content",
                    "confidence": 100,
                    "element_path": "body",
                    "id": "dummy",
                    "label": "prose",
                    "version": "2-0-0"
                },
                {
                    "classifier": "classifier-language",
                    "confidence": 76,
                    "element_path": "body",
                    "id": "dummy",
                    "label": "en",
                    "version": "1-0-0"
                },
                {
                    "classifier": "classifier-threat",
                    "confidence": 100,
                    "id": "dummy",
                    "label": "information-security/anonymization",
                    "version": "3-0-0"
                }
            ],
            "labels_url": "https://www.virustotal.com/v4/dtm/docs/message/dummy/labels",
            "monitor_id": "dummy_monitor_id_000",
            "monitor_version": 1,
            "severity": "medium",
            "severity_reasoning": {
                "rule": ""
            },
            "similarity_score": 0.9554455,
            "status": "new",
            "tags": [
                "attempt"
            ],
            "title": "Found topic \"google\" posted by actor \"test \" on channel \"chasinchicken1\"",
            "topic_matches": [
                {
                    "offsets": [
                        0,
                        6
                    ],
                    "term": "google",
                    "topic_id": "dummy",
                    "value": "Google"
                },
                {
                    "topic_id": "doc_type:message",
                    "value": "message"
                }
            ],
            "topics": [
                {
                    "confidence": 81,
                    "entity_locations": [
                        {
                            "element_path": "body",
                            "offsets": [
                                666,
                                674
                            ]
                        }
                    ],
                    "extractor": "analysis-pipeline.nerprocessor-nerenglish-gpu",
                    "extractor_version": "4-0-2",
                    "id": "dummy",
                    "type": "product",
                    "value": "Google"
                },
                {
                    "confidence": 100,
                    "entity_locations": [
                        {
                            "element_path": "body",
                            "offsets": [
                                262,
                                267,
                                1183,
                                1188
                            ]
                        }
                    ],
                    "extractor": "dummy_extractor",
                    "extractor_version": "4-0-2",
                    "id": "dummy",
                    "type": "organization",
                    "value": "Google"
                }
            ],
            "topics_url": "https://www.virustotal.com/v4/dtm/docs/message/dummy/topics",
            "updated_at": "2025-08-19T10:13:25.352Z"
        }
    }
}

Human Readable Output

DTM Alert

Alert ID Title Alert Summary Alert Type Severity Status Monitor ID Indicator Score Created At Updated At Tags
dummy_alert_001 Found topic “google” posted by actor “test” on channel “chasinchicken1” This advertisement details a sophisticated phishing-as-a-service platform verified email spoofing capabilities. Message Medium New dummy_monitor_id_000 92 2025-08-19T09:29:31.827Z 2025-08-19T10:13:25.352Z attempt

gti-dtm-alert-status-update


Update the status of DTM alert.

Base Command

gti-dtm-alert-status-update

Input

Argument Name Description Required
alert_id Specify ID of the alert.

Note: Use gti-dtm-alert-list to retrive the Alert ID.
Required
status Specify status of the alert. Possible values are: new, read, in_progress, escalated, closed, no_action_required, duplicate, not_relevant, tracked_external. Required

Context Output

Path Type Description
GoogleThreatIntelligenceDTMAlerts.Alerts.id String Unique identifier for the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.monitor_id String Identifier of the monitoring source that generated the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.__id String Unique document ID associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.__type String Type of document associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.body String Full content or message body of the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.channel_id String ID of the channel where the alert was observed.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.channel_info.description String Description of the channel where the alert was detected.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.channel_url String URL of the detected channel.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.invite_url String Invite link of the detected channel, if available.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.messenger.id String Identifier of the messenger platform linked to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.messenger.name String Name of the messenger platform.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.channel.name String Name of the channel where the content was found.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.ingested Date Date and time when the document was ingested into the system.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.message_id String Identifier of the specific message triggering the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.messenger.id String Messenger platform ID associated with the message.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.messenger.name String Name of the messenger platform associated with the message.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.avatar_file.hashes.sha256 String SHA-256 hash of the sender’s avatar file.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.avatar_file.mime_type String MIME type of the sender’s avatar file.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.identity.first_name String First name of the sender.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.identity.last_name String Last name of the sender.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.identity.name String Full name of the sender.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.telegram.name String Telegram username of the sender.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.sender.telegram.user_id Number Telegram user ID of the sender.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.source String Source of the document or content triggering the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc.timestamp Date Timestamp when the message or document was created.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.id String Unique identifier of the label assigned to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.classifier String Classifier name used for label assignment.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.version String Version of the classifier or labeling process.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.label String Name of the label assigned to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.confidence Number Confidence score of the assigned label.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels.element_path String Path of the element where the label was applied.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.id String Unique identifier of the extracted topic.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.type String Type of the extracted topic.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.value String Value of the extracted topic.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.extractor String Name of the topic extraction tool.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.extractor_version String Version of the topic extractor used.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.entity_locations.element_path String Path of the element where the entity was detected.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics.entity_locations.offsets Number Character offsets of the detected entity in the document.
GoogleThreatIntelligenceDTMAlerts.Alerts.topic_matches.topic_id String Identifier of the matched topic.
GoogleThreatIntelligenceDTMAlerts.Alerts.topic_matches.value String Matched value for the topic.
GoogleThreatIntelligenceDTMAlerts.Alerts.label_matches List List of labels matched for the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc_matches.match_path String Path within the document where a match occurred.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc_matches.locations.offsets Number Offset positions of the document match.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc_matches.locations.value String Value of the matched document content.
GoogleThreatIntelligenceDTMAlerts.Alerts.tags List Tags associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.created_at Date Date and time when the alert was created.
GoogleThreatIntelligenceDTMAlerts.Alerts.updated_at Date Date and time when the alert was last updated.
GoogleThreatIntelligenceDTMAlerts.Alerts.labels_url String URL to fetch labels associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.topics_url String URL to fetch topics associated with the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.doc_url String URL of the original document related to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.status String Current status of the alert (e.g., open, closed, triaged).
GoogleThreatIntelligenceDTMAlerts.Alerts.alert_type String Type or category of the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.alert_summary String Summary of the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.title String Title of the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.email_sent_at String Timestamp when the alert email was sent.
GoogleThreatIntelligenceDTMAlerts.Alerts.indicator_mscore Number Malicious score of the indicator related to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.severity String Severity level of the alert (e.g., low, medium, high).
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence Number Confidence score of the alert detection.
GoogleThreatIntelligenceDTMAlerts.Alerts.aggregated_under_id String ID under which the alert has been aggregated.
GoogleThreatIntelligenceDTMAlerts.Alerts.has_analysis Boolean Indicates whether the alert has an associated analysis.
GoogleThreatIntelligenceDTMAlerts.Alerts.ai_doc_summary String AI-generated summary of the document related to the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.similarity_score Number Similarity score between this alert and related alerts.
GoogleThreatIntelligenceDTMAlerts.Alerts.severity_reasoning.rule String Rule used to determine the severity of the alert.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.version String Version of the confidence reasoning model.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.response_count Number Number of responses contributing to confidence reasoning.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.malicious_count Number Number of malicious detections contributing to confidence.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.benign_count Number Number of benign detections contributing to confidence.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.confidence_count Number Total number of samples considered for confidence calculation.
GoogleThreatIntelligenceDTMAlerts.Alerts.confidence_reasoning.explanation String Explanation behind the confidence score.
GoogleThreatIntelligenceDTMAlerts.Alerts.ignore Boolean Indicates if the alert should be ignored.
GoogleThreatIntelligenceDTMAlerts.Alerts.monitor_version Number Version of the monitoring source generating the alert.

Command example

!gti-dtm-alert-status-update alert_id=dummyalertid_001 status=duplicate

Context Example

{
    "GoogleThreatIntelligenceDTMAlerts": {
        "Alerts": {
            "aggregated_under_id": "dummy_monitor_id_001",
            "ai_doc_summary": "This advertisement for \"Angel Mailer\" highlights its capabilities for sending spoofed emails.",
            "alert_summary": "Angel Mailer the best possible solution for all your mailing needs Our main features…",
            "alert_type": "Message",
            "confidence": 0.5404703550433493,
            "confidence_reasoning": {
                "benign_count": 0,
                "malicious_count": 0,
                "response_count": 0,
                "version": ""
            },
            "created_at": "2025-08-27T19:05:38.521Z",
            "doc_matches": [
                {
                    "locations": [
                        {
                            "value": "full"
                        }
                    ],
                    "match_path": "body"
                }
            ],
            "doc_url": "https://www.virustotal.com/v4/dtm/docs/message/dummyid",
            "email_sent_at": "",
            "has_analysis": false,
            "id": "dummy_alert_id_001",
            "ignore": false,
            "indicator_mscore": 92,
            "labels_url": "https:///www.virustotal.com/v4/dtm/docs/message/dummyid/labels",
            "monitor_id": "dummy_monitor_id",
            "monitor_version": 1,
            "severity": "medium",
            "severity_reasoning": {
                "rule": ""
            },
            "similarity_score": 0.9554455,
            "status": "duplicate",
            "title": "Found topic \"google\" posted by actor \"test\" on Telegram channel \"chasinchicken1\"",
            "topic_matches": [
                {
                    "offsets": [
                        0,
                        6
                    ],
                    "term": "google",
                    "topic_id": "000101000010",
                    "value": "Google"
                },
                {
                    "topic_id": "doc_type:message",
                    "value": "message"
                }
            ],
            "topics_url": "https:///www.virustotal.com/topics",
            "updated_at": "2025-08-28T06:25:10.535Z"
        }
    }
}

Human Readable Output

Alert Status Updated Successfully

Alert ID Status
dummy_alert_id_001 Duplicate

Configuration parameters

  • credentials — (required)
  • isFetch — Fetch incidents
  • max_fetch — Max Fetch
  • first_fetch — First Fetch Time
  • mirror_direction — Mirroring Direction
  • alert_type — Alert Type
  • alert_monitor_ids — Alert Monitor ID
  • alert_status — Alert Status
  • alert_severity — Alert Severity
  • alert_tags — Alert Tags
  • alert_match_value — Alert Match Value
  • alert_mscore_gte — Alert mscore
  • alert_search — Alert Search
  • proxy — Use system proxy settings
  • insecure — Trust any certificate (not secure)
  • incidentType — Incident type
  • incidentFetchInterval — Incidents Fetch Interval

Commands (3)

  • gti-dtm-alert-get

    Get a particular DTM Alert by ID.

  • gti-dtm-alert-list

    Search the DTM Alerts with provided filter arguments.

  • gti-dtm-alert-status-update

    Update the status of DTM alert.

from GoogleThreatIntelligenceDTMAlerts import (
    DEFAULT_MAX_FETCH,
    MAX_FETCH,
    Client,
    BASE_URL,
    ENDPOINTS,
    MESSAGES,
    ERROR_MESSAGES,
    ALERTS_ALERT_TYPE_LIST,
    ALERTS_STATUS_HUMAN_READABLE,
    ALERTS_SEVERITY_HUMAN_READABLE,
    ALERTS_ORDER_HR_LIST,
    ALERTS_SORT_HR_LIST,
)
from CommonServerPython import *  # noqa # pylint: disable=unused-wildcard-import
import json
import pytest


# Helper Functions
def util_load_json(path):
    """Load JSON data from file."""
    with open(path, encoding="utf-8") as f:
        return json.loads(f.read())


@pytest.fixture
def mock_client(mocker):
    """Create a mocked client for testing."""
    return Client(verify_certificate=False, proxy=False, api_key="test_api_key")


def test_client_initialization():
    """Test Client class initialization."""
    client = Client(verify_certificate=True, proxy=False, api_key="test_key_123")

    # Verify client is properly initialized
    assert client._base_url == BASE_URL
    assert client._headers["x-apikey"] == "test_key_123"
    assert client._headers["x-tool"] == "CortexGTI"
    assert client._headers["Accept"] == "application/json"
    assert client._headers["Content-Type"] == "application/json"


def test_test_module_success(mock_client, requests_mock):
    """Test test_module function returns 'ok' when API call succeeds."""
    from GoogleThreatIntelligenceDTMAlerts import test_module

    requests_mock.get(f'{BASE_URL}/{ENDPOINTS["alert_list"]}', json={}, status_code=200)
    result = test_module(client=mock_client)

    # Verify the function returns "ok"
    assert result == "ok"


def test_test_module_invalid_api_key(mock_client, requests_mock):
    """Test test_module function returns 'ok' when API call succeeds."""
    from GoogleThreatIntelligenceDTMAlerts import test_module

    requests_mock.get(
        f'{BASE_URL}/{ENDPOINTS["alert_list"]}',
        json={"error": {"code": "WrongCredentialsError", "message": "Wrong API key"}},
        status_code=401,
    )
    with pytest.raises(DemistoException) as e:
        test_module(client=mock_client)

    assert (
        str(e.value) == "401 Unauthorized request: Invalid API key provided "
        "{'error': {'code': 'WrongCredentialsError', 'message': 'Wrong API key'}}."
    )


def test_main_test_module_success(mocker, requests_mock):
    """
    Given:
    - Valid parameters and test-module command.

    When:
    - Running the main function.

    Then:
    - Validate that test_module is called and returns 'ok'.
    """
    from GoogleThreatIntelligenceDTMAlerts import main

    # Mock demisto functions
    mock_params = {"credentials": {"password": "test_api_key"}, "insecure": False, "proxy": False}
    mock_demisto = mocker.patch("GoogleThreatIntelligenceDTMAlerts.demisto")
    mock_demisto.params.return_value = mock_params
    mock_demisto.command.return_value = "test-module"
    mock_demisto.args.return_value = {}
    mock_demisto.debug = mocker.Mock()

    # Mock return_results and return_error
    mock_return_results = mocker.patch("GoogleThreatIntelligenceDTMAlerts.return_results")
    mock_return_error = mocker.patch("GoogleThreatIntelligenceDTMAlerts.return_error")

    # Mock the API call for test_module
    requests_mock.get(f'{BASE_URL}/{ENDPOINTS["alert_list"]}', json={}, status_code=200)

    # Call main
    main()

    # Assertions
    mock_demisto.command.assert_called_once()
    mock_return_results.assert_called_once_with("ok")
    mock_return_error.assert_not_called()


@pytest.mark.parametrize(
    "command, args, mock_api_response, expected_result_type",
    [("test-module", {}, {}, str), ("gti-dtm-alert-get", {"alert_id": "test_123"}, "dtm_alert_get.json", type(None))],
)
def test_main_try_block_success_paths(mocker, requests_mock, command, args, mock_api_response, expected_result_type):
    """
    Given:
    - Valid parameters and different commands.

    When:
    - Running the main function try block.

    Then:
    - Validate that the appropriate command is executed and return_results is called.
    """
    from GoogleThreatIntelligenceDTMAlerts import main

    # Mock demisto functions
    mock_params = {"credentials": {"password": "test_api_key"}, "insecure": False, "proxy": False}
    mock_demisto = mocker.patch("GoogleThreatIntelligenceDTMAlerts.demisto")
    mock_demisto.params.return_value = mock_params
    mock_demisto.command.return_value = command
    mock_demisto.args.return_value = args
    mock_demisto.debug = mocker.Mock()

    # Mock return_results and return_error
    mock_return_results = mocker.patch("GoogleThreatIntelligenceDTMAlerts.return_results")
    mock_return_error = mocker.patch("GoogleThreatIntelligenceDTMAlerts.return_error")

    # Mock API responses based on command
    if command == "test-module":
        requests_mock.get(f'{BASE_URL}/{ENDPOINTS["alert_list"]}', json=mock_api_response, status_code=200)
    elif command == "gti-dtm-alert-get":
        mock_response = util_load_json(f"test_data/{mock_api_response}")
        requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_get'].format(args['alert_id'])}", json=mock_response)

    # Call main
    main()

    # Assertions
    mock_return_results.assert_called_once()
    mock_return_error.assert_not_called()

    # Verify the result type if needed
    if command == "test-module":
        mock_return_results.assert_called_with("ok")


def test_main_try_block_unknown_command_exception(mocker):
    """
    Given:
    - An unknown command that raises NotImplementedError.

    When:
    - Running the main function with unknown command.

    Then:
    - Validate that NotImplementedError is caught and return_error is called.
    """
    from GoogleThreatIntelligenceDTMAlerts import main

    # Mock demisto functions
    mock_params = {"credentials": {"password": "test_api_key"}, "insecure": False, "proxy": False}
    mock_demisto = mocker.patch("GoogleThreatIntelligenceDTMAlerts.demisto")
    mock_demisto.params.return_value = mock_params
    mock_demisto.command.return_value = "unknown-command"
    mock_demisto.args.return_value = {}

    # Mock return functions
    mock_return_results = mocker.patch("GoogleThreatIntelligenceDTMAlerts.return_results")
    mock_return_error = mocker.patch("GoogleThreatIntelligenceDTMAlerts.return_error")

    # Call main
    main()

    # Verify exception handling
    mock_return_error.assert_called_once()
    error_message = mock_return_error.call_args[0][0]

    # Verify error message contains expected content
    assert "Failed to execute unknown-command command" in error_message
    assert "Command unknown-command is not implemented" in error_message

    mock_return_results.assert_not_called()


def test_gti_alert_get_command_success(mock_client, requests_mock):
    """
    Given:
    - A valid alert ID.

    When:
    - Running the !gti-alert-get command.

    Then:
    - Validate the command results are valid.
    """
    from GoogleThreatIntelligenceDTMAlerts import gti_dtm_alert_get_command

    mock_response = util_load_json("test_data/dtm_alert_get.json")
    with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_data/dtm_alert_get_human_readable.md")) as f:
        dtm_alert_list_hr = f.read()

    requests_mock.get(
        f"{BASE_URL}/{ENDPOINTS['alert_get'].format('dummy_0000')}?sanitize=true&refs=true&truncate=1000", json=mock_response
    )

    test_args = {
        "alert_id": "dummy_0000",
        "truncate": "1000",
        "sanitize": "Yes",
        "include_more_details": "Yes",
    }

    results = gti_dtm_alert_get_command(client=mock_client, args=test_args)

    assert results.raw_response == mock_response
    assert results.readable_output == dtm_alert_list_hr
    assert results.outputs == [mock_response]


def test_gti_alert_get_command_no_record_found(mock_client, requests_mock):
    """
    Given:
    - An invalid alert ID.

    When:
    - Running the !gti-alert-get command.

    Then:
    - Validate the command results are valid.
    """
    from GoogleThreatIntelligenceDTMAlerts import gti_dtm_alert_get_command

    requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_get'].format('dummy_0000')}?sanitize=true&refs=true&truncate=1000", json={})

    test_args = {
        "alert_id": "dummy_0000",
        "truncate": "1000",
        "sanitize": "Yes",
        "include_more_details": "Yes",
    }

    results = gti_dtm_alert_get_command(client=mock_client, args=test_args)

    assert results.readable_output == "No DTM Alert was found for the given argument(s)."
    assert results.outputs is None
    assert results.raw_response is None


@pytest.mark.parametrize(
    "args, exception, error",
    [
        ({"alert_id": ""}, ValueError, MESSAGES["REQUIRED_ARGUMENT"].format("alert_id")),
        ({"alert_id": "dummy123", "truncate": "-1"}, ValueError, ERROR_MESSAGES["INVALID_DTM_ALERT_TRUNCATE"].format("-1")),
    ],
)
def test_gti_dtm_alert_get_command_when_invalid_input(args, mock_client, exception, error):
    """
    Given:
    - An invalid input.

    When:
    - Running the !gti-dtm-alert-get command.

    Then:
    - Validate the command results are valid.
    """
    from GoogleThreatIntelligenceDTMAlerts import gti_dtm_alert_get_command

    with pytest.raises(exception) as e:
        gti_dtm_alert_get_command(client=mock_client, args=args)

    assert str(e.value) == error


def test_gti_dtm_alerts_list_command_success(mock_client, requests_mock):
    """
    Given:
    - A valid query

    When:
    - Running the !gti-dtm-alerts-list command

    Then:
    - Validate the command results are valid
    """
    from GoogleThreatIntelligenceDTMAlerts import gti_dtm_alert_list_command

    mock_response = util_load_json("test_data/dtm_alerts_lists.json")

    with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_data/dtm_alerts_list_human_readable.md")) as f:
        dtm_alerts_list_hr = f.read()

    test_args = {
        "page_size": "1",
        "order": "desc",
        "sort": "created_at",
        "start_date": "2025-05-20T12:19:22.824000Z",
        "end_date": "2025-05-20T12:19:27.824000Z",
        "monitor_id": "dummy_monitor",
        "tags": "attempt",
        "status": "read",
        "alert_type": "Message",
        "severity": "low",
        "mscore_gte": "11",
        "include_more_details": "Yes",
        "include_monitor_name": "Yes",
        "has_analysis": "True",
        "search": "social",
        "match_value": "access",
    }

    # Mock the API call without params in requests_mock
    requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_list']}", json=mock_response)

    results = gti_dtm_alert_list_command(client=mock_client, args=test_args)

    assert results.readable_output == dtm_alerts_list_hr
    assert results.outputs == mock_response["alerts"]


@pytest.mark.parametrize(
    "args, exception, error",
    [
        ({"page_size": "-1"}, ValueError, ERROR_MESSAGES["INVALID_PAGE_SIZE"].format("-1", DEFAULT_MAX_FETCH)),
        ({"page_size": "26"}, ValueError, ERROR_MESSAGES["INVALID_PAGE_SIZE"].format("26", DEFAULT_MAX_FETCH)),
        ({"order": "test"}, ValueError, ERROR_MESSAGES["INVALID_ARGUMENT"].format("test", "order", ALERTS_ORDER_HR_LIST)),
        ({"sort": "test"}, ValueError, ERROR_MESSAGES["INVALID_ARGUMENT"].format("test", "sort", ALERTS_SORT_HR_LIST)),
        (
            {"severity": "test"},
            ValueError,
            ERROR_MESSAGES["INVALID_ARGUMENT"].format("test", "severity", ALERTS_SEVERITY_HUMAN_READABLE),
        ),
        ({"mscore_gte": "-1"}, ValueError, ERROR_MESSAGES["INVALID_MSCORE_GTE"].format("-1")),
        ({"mscore_gte": "101"}, ValueError, ERROR_MESSAGES["INVALID_MSCORE_GTE"].format("101")),
        (
            {"alert_type": "test"},
            ValueError,
            ERROR_MESSAGES["INVALID_ARGUMENT"].format("test", "type", ALERTS_ALERT_TYPE_LIST),
        ),
        (
            {"status": "test"},
            ValueError,
            ERROR_MESSAGES["INVALID_ARGUMENT"].format("test", "status", ALERTS_STATUS_HUMAN_READABLE),
        ),
    ],
)
def test_gti_dtm_alerts_list_command_when_invalid_input(args, mocker, exception, error):
    """
    Given:
    - An invalid input

    When:
    - Running the !gti-dtm-alerts-list command

    Then:
    - Validate the command results are valid
    """
    from GoogleThreatIntelligenceDTMAlerts import gti_dtm_alert_list_command

    with pytest.raises(exception) as e:
        gti_dtm_alert_list_command(mock_client, args)

    assert str(e.value) == error


def test_gti_dtm_alerts_list_no_records_found(mock_client, requests_mock):
    """
    Given:
    - No records found

    When:
    - Running the !gti-dtm-alerts-list command

    Then:
    - Validate the command results are valid
    """
    from GoogleThreatIntelligenceDTMAlerts import gti_dtm_alert_list_command

    test_args = {
        "page_size": "1",
        "order": "desc",
        "sort": "created_at",
        "start_time": "2025-05-20T12:19:22.824000Z",
        "end_time": "2025-05-20T12:19:27.824000Z",
        "monitor_id": "dummymonitor",
        "tags": "attempt ,test",
        "status": "read ,New",
        "alert_type": "Message ",
        "severity": "low ,High",
        "mscore_gte": "11",
        "include_more_details": "Yes",
        "include_monitor_name": "Yes",
        "has_analysis": "True",
        "search": "surgesocialmarket",
        "match_value": "access",
    }
    requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_list']}", json={})

    results = gti_dtm_alert_list_command(mock_client, test_args)

    assert results.readable_output == "No DTM Alerts were found for the given argument(s)."
    assert results.outputs is None


def test_gti_update_dtm_alert_status_command_success(mock_client, requests_mock):
    """
    Given:
    - A valid alert ID and status

    When:
    - Running the !gti-update-dtm-alert-status command

    Then:
    - Validate the command results are valid
    """
    from GoogleThreatIntelligenceDTMAlerts import gti_dtm_alert_status_update_command

    mock_response = util_load_json("test_data/dtm_alert_status_update.json")
    with open(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_data/dtm_alert_status_update_human_readable.md")
    ) as f:
        dtm_alert_list_hr = f.read()

    test_args = {
        "alert_id": "dummy_alert_id",
        "status": "read",
    }
    requests_mock.patch(f"{BASE_URL}/dtm/alerts/dummy_alert_id", json=mock_response)

    results = gti_dtm_alert_status_update_command(mock_client, test_args)

    assert results.readable_output == dtm_alert_list_hr
    assert results.outputs == [mock_response]


@pytest.mark.parametrize(
    "args, exception, error",
    [
        ({"alert_id": ""}, ValueError, MESSAGES["REQUIRED_ARGUMENT"].format("alert_id")),
        ({"alert_id": "dummy123", "status": ""}, ValueError, MESSAGES["REQUIRED_ARGUMENT"].format("status")),
        (
            {"alert_id": "dummy123", "status": "test"},
            ValueError,
            ERROR_MESSAGES["INVALID_ARGUMENT"].format("test", "status", ALERTS_STATUS_HUMAN_READABLE),
        ),
    ],
)
def test_gti_update_dtm_alert_status_command_when_invalid_input(args, mock_client, exception, error):
    """
    Given:
    - An invalid input

    When:
    - Running the !gti-update-dtm-alert-status command

    Then:
    - Validate the command results are valid
    """
    from GoogleThreatIntelligenceDTMAlerts import gti_dtm_alert_status_update_command

    with pytest.raises(exception) as e:
        gti_dtm_alert_status_update_command(mock_client, args)

    assert str(e.value) == error


def test_fetch_incidents_test_connectivity_dtm_alerts(mock_client, requests_mock, mocker):
    """Test test_module function when fetch is enabled."""
    from GoogleThreatIntelligenceDTMAlerts import test_module

    params = {"isFetch": True, "max_fetch": "10", "first_fetch": "1 days", "mirror_direction": "Outgoing"}

    # Mock demisto.params() to return our test parameters
    mocker.patch.object(demisto, "params", return_value=params)

    requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_list']}", json={}, status_code=200)

    result = test_module(client=mock_client)

    assert result == "ok"


def test_fetch_incidents_dtm_alerts_success(mock_client, requests_mock, mocker):
    from GoogleThreatIntelligenceDTMAlerts import fetch_incidents

    mock_response = util_load_json(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_data/fetch_incident_incidents_dtm_alerts_success.json")
    )

    incidents = util_load_json(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_data/fetch_incident_dtm_alerts_success_incidents.json")
    )
    alert_ids = [alert["id"] for alert in mock_response["alerts"]]

    requests_mock.get(
        f"{BASE_URL}/{ENDPOINTS['alert_list']}",
        json=mock_response,
        headers={"link": f'<{BASE_URL}/{ENDPOINTS["alert_list"]}?page=next_page_token>'},
    )

    params = {
        "isFetch": False,
        "alert_match_value": ["attempt"],
        "alert_monitor_ids": ["monitor_id_000"],
        "alert_severity": ["Low", "Medium"],
        "alert_status": ["New"],
        "alert_tags": ["intrustion", "network"],
        "alert_type": ["Message"],
        "first_fetch": "1 days",
        "max_fetch": 3,
        "mirror_direction": "Outgoing",
    }
    mocker.patch.object(demisto, "params", return_value=params)

    alert_incidents, next_run_params = fetch_incidents(client=mock_client, params=params, last_run={})

    assert next_run_params["alert_ids"] == alert_ids
    assert next_run_params["last_alert_created_at"] == "2025-08-19T14:30:45.97Z"
    assert alert_incidents == incidents


def test_fetch_incidents_dtm_alerts_success_with_last_run(mock_client, requests_mock, mocker):
    from GoogleThreatIntelligenceDTMAlerts import fetch_incidents

    params = {
        "isFetch": False,
        "alert_match_value": ["attempt"],
        "alert_monitor_ids": ["monitor_id_000"],
        "alert_severity": ["Low", "Medium"],
        "alert_status": ["New"],
        "alert_tags": ["intrustion", "network"],
        "alert_type": ["Message"],
        "first_fetch": "1 days",
        "max_fetch": 3,
        "mirror_direction": "Outgoing",
    }
    mocker.patch.object(demisto, "params", return_value=params)
    last_run = {
        "alert_ids": ["dummy_001"],
        "last_alert_created_at": "2025-01-01T14:26:37Z",
    }

    mock_response = util_load_json(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_data/fetch_incident_incidents_dtm_alerts_success.json")
    )

    incidents = util_load_json(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_data/fetch_incident_dtm_alerts_success_incidents.json")
    )
    alert_ids = [alert["id"] for alert in mock_response["alerts"]]

    alert_ids_list = last_run["alert_ids"] + alert_ids

    requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_list']}", json=mock_response)

    alert_incidents, next_run_params = fetch_incidents(client=mock_client, params=params, last_run=last_run)

    assert next_run_params["alert_ids"] == alert_ids_list
    assert next_run_params["last_alert_created_at"] == "2025-08-19T14:30:45.97Z"
    assert alert_incidents == incidents


def test_fetch_incidents_dtm_alerts_skip_duplicate_alerts(mock_client, requests_mock, mocker):
    from GoogleThreatIntelligenceDTMAlerts import fetch_incidents

    params = {
        "isFetch": False,
        "alert_match_value": ["attempt"],
        "alert_monitor_ids": ["monitor_id_000"],
        "alert_severity": ["Low", "Medium"],
        "alert_status": ["New"],
        "alert_tags": ["intrustion", "network"],
        "alert_type": ["Message"],
        "first_fetch": "1 days",
        "max_fetch": 25,
        "mirror_direction": "Outgoing",
    }
    mocker.patch.object(demisto, "params", return_value=params)

    last_run = {
        "alert_ids": ["dummy_00"],
        "last_alert_created_at": "2025-08-10T14:26:37Z",
    }

    mock_response = util_load_json(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_data/fetch_incident_incidents_dtm_alerts_success.json")
    )

    alert_skip_dup_incidents = util_load_json(
        os.path.join(
            os.path.dirname(os.path.realpath(__file__)), "test_data/fetch_incident_dtm_alerts_incidents_with_skip_duplicate.json"
        )
    )
    alert_ids = [alert["id"] for alert in mock_response["alerts"]]

    requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_list']}", json=mock_response)

    alert_incidents, next_run_params = fetch_incidents(client=mock_client, params=params, last_run=last_run)

    assert next_run_params["alert_ids"] == alert_ids
    assert next_run_params["last_alert_created_at"] == "2025-08-19T14:30:45.97Z"
    assert alert_incidents == alert_skip_dup_incidents


def test_fetch_incidents_large_fetch_with_pagination_token(mock_client, requests_mock, mocker):
    """Test large fetch using pagination token from previous run."""
    from GoogleThreatIntelligenceDTMAlerts import fetch_incidents

    params = {
        "isFetch": False,
        "first_fetch": "1 days",
        "max_fetch": 50,
        "mirror_direction": "Outgoing",
    }
    mocker.patch.object(demisto, "params", return_value=params)

    last_run = {
        "alert_ids": ["alert_0"],
        "last_alert_created_at": "2025-08-19T14:30:00.97Z",
    }

    mock_response_1 = util_load_json(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_data/dtm_alert_large_fetch_response.json")
    )

    requests_mock.get(
        f"{BASE_URL}/{ENDPOINTS['alert_list']}",
        [
            {"json": mock_response_1, "headers": {"link": '<url?page=token2>; rel="next"'}},
            {"json": mock_response_1, "headers": {}},
        ],
    )

    alert_incidents, next_run_params = fetch_incidents(client=mock_client, params=params, last_run=last_run)

    assert len(alert_incidents) == 48
    assert next_run_params["last_alert_created_at"] == "2025-08-19T14:30:24.97Z"


def test_fetch_incidents_large_fetch_no_alerts_stops_pagination(mock_client, requests_mock, mocker):
    """Test large fetch stops when API returns no alerts."""
    from GoogleThreatIntelligenceDTMAlerts import fetch_incidents

    params = {
        "isFetch": False,
        "first_fetch": "1 days",
        "max_fetch": 100,
        "mirror_direction": "Outgoing",
    }
    mocker.patch.object(demisto, "params", return_value=params)

    mock_response_1 = util_load_json(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_data/dtm_alert_large_fetch_response.json")
    )
    mock_response_2 = {"alerts": []}  # No alerts returned

    requests_mock.get(
        f"{BASE_URL}/{ENDPOINTS['alert_list']}",
        [
            {"json": mock_response_1, "headers": {"link": '<url?page=token2>; rel="next"'}},
            {"json": mock_response_2, "headers": {}},
        ],
    )

    alert_incidents, next_run_params = fetch_incidents(client=mock_client, params=params, last_run={})

    # Should stop after first call when second returns no alerts
    assert len(alert_incidents) == 25
    assert next_run_params["last_alert_created_at"] == "2025-08-19T14:30:24.97Z"
    assert next_run_params["alert_ids"] == [alert["id"] for alert in mock_response_1["alerts"]]


def test_fetch_incidents_large_fetch_test_connectivity(mock_client, requests_mock, mocker):
    """Test large fetch exits after first call during test connectivity."""
    from GoogleThreatIntelligenceDTMAlerts import fetch_incidents

    params = {
        "isFetch": False,
        "first_fetch": "1 days",
        "max_fetch": 50,
        "mirror_direction": "Outgoing",
    }
    mocker.patch.object(demisto, "params", return_value=params)

    mock_response = util_load_json(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_data/dtm_alert_large_fetch_response.json")
    )

    requests_mock.get(
        f"{BASE_URL}/{ENDPOINTS['alert_list']}",
        json=mock_response,
        headers={"link": '<url?page=token2>; rel="next"'},
    )

    alert_incidents, next_run_params = fetch_incidents(client=mock_client, params=params, last_run={}, is_test=True)

    # Should exit after first call in test mode
    assert len(alert_incidents) == 0  # is_test returns before creating incidents
    # In test mode, next_run_params should be empty since we return early
    assert next_run_params == {}


def test_fetch_incidents_large_fetch_timeout(mock_client, requests_mock, mocker):
    """Test large fetch handles timeout after 4 minutes."""
    from GoogleThreatIntelligenceDTMAlerts import fetch_incidents

    params = {
        "isFetch": False,
        "first_fetch": "1 days",
        "max_fetch": 100,
        "mirror_direction": "Outgoing",
    }
    mocker.patch.object(demisto, "params", return_value=params)

    # Mock has_passed_time_threshold to simulate timeout after first iteration
    mocker.patch(
        "GoogleThreatIntelligenceDTMAlerts.has_passed_time_threshold",
        side_effect=[False, True],  # First call: no timeout, Second call: timeout
    )

    mock_response = util_load_json(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_data/dtm_alert_large_fetch_response.json")
    )

    requests_mock.get(
        f"{BASE_URL}/{ENDPOINTS['alert_list']}",
        json=mock_response,
        headers={"link": '<url?page=token2>; rel="next"'},
    )

    alert_incidents, next_run_params = fetch_incidents(client=mock_client, params=params, last_run={})

    # Should have fetched alerts from first call before timeout
    assert len(alert_incidents) == 25  # Should have alerts from first call only
    assert next_run_params["last_alert_created_at"] == "2025-08-19T14:30:24.97Z"


@pytest.mark.parametrize(
    "params, exception, error",
    [
        ({"max_fetch": "-1"}, ValueError, ERROR_MESSAGES["INVALID_MAX_FETCH"].format("-1", MAX_FETCH)),
        ({"max_fetch": "0"}, ValueError, ERROR_MESSAGES["INVALID_MAX_FETCH"].format("0", MAX_FETCH)),
        ({"max_fetch": "101"}, ValueError, ERROR_MESSAGES["INVALID_MAX_FETCH"].format("101", MAX_FETCH)),
        ({"alert_mscore_gte": "-1"}, ValueError, ERROR_MESSAGES["INVALID_MSCORE_GTE"].format("-1")),
        ({"alert_mscore_gte": "101"}, ValueError, ERROR_MESSAGES["INVALID_MSCORE_GTE"].format("101")),
        (
            {"alert_type": "test"},
            ValueError,
            ERROR_MESSAGES["INVALID_ARGUMENT"].format("test", "type", ALERTS_ALERT_TYPE_LIST),
        ),
        (
            {"alert_status": "test"},
            ValueError,
            ERROR_MESSAGES["INVALID_ARGUMENT"].format("test", "status", ALERTS_STATUS_HUMAN_READABLE),
        ),
        (
            {"alert_severity": "test"},
            ValueError,
            ERROR_MESSAGES["INVALID_ARGUMENT"].format("test", "severity", ALERTS_SEVERITY_HUMAN_READABLE),
        ),
    ],
)
def test_validate_configuration_params_invalid(params, exception, error, mock_client, requests_mock):
    from GoogleThreatIntelligenceDTMAlerts import fetch_incidents

    requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_list']}", json={})

    with pytest.raises(exception) as error_message:
        fetch_incidents(client=mock_client, params=params, last_run={})

    assert str(error_message.value) == error


def test_update_remote_system_command_status_update_incident_closed(mocker, requests_mock, mock_client):
    """
    Given:
    - Valid arguments with incident status DONE and incident changed

    When:
    - Running update_remote_system_command

    Then:
    - Status should be updated to 'closed' via a PATCH request.
    """
    from GoogleThreatIntelligenceDTMAlerts import update_remote_system_command

    # Mock UpdateRemoteSystemArgs
    mock_args = mocker.Mock()
    mock_args.remote_incident_id = "remote_123"
    mock_args.data = {"alertid": "alert_456"}
    mock_args.inc_status = 2  # IncidentStatus.DONE
    mock_args.delta = {}
    mock_args.incident_changed = True

    mocker.patch("GoogleThreatIntelligenceDTMAlerts.UpdateRemoteSystemArgs", return_value=mock_args)

    # Mock the API endpoint
    requests_mock.patch(f"{BASE_URL}/{ENDPOINTS['alert_update'].format('alert_456')}", json={"success": True})

    args = {
        "remote_incident_id": "remote_123",
        "data": {"alertid": "alert_456"},
        "inc_status": 2,  # IncidentStatus.DONE
        "delta": {},
        "incident_changed": True,
    }

    result = update_remote_system_command(mock_client, args)

    # Verify the result
    assert result == "remote_123"

    # Verify the PATCH request was made with the correct payload
    history = requests_mock.request_history
    assert len(history) == 1
    assert history[0].method == "PATCH"
    assert history[0].json() == {"status": "closed"}


def test_update_remote_system_command_incident_active_with_no_delta(mocker, requests_mock, mock_client):
    """
    Given:
    - Valid arguments with incident status ACTIVE, no delta, and incident changed

    When:
    - Running update_remote_system_command

    Then:
    - Status should be updated to 'in_progress' via a PATCH request.
    """
    from GoogleThreatIntelligenceDTMAlerts import update_remote_system_command

    # Mock UpdateRemoteSystemArgs
    mock_args = mocker.Mock()
    mock_args.remote_incident_id = "remote_123"
    mock_args.data = {"alertid": "alert_456"}
    mock_args.inc_status = 1  # IncidentStatus.ACTIVE
    mock_args.delta = {}
    mock_args.incident_changed = True

    mocker.patch("GoogleThreatIntelligenceDTMAlerts.UpdateRemoteSystemArgs", return_value=mock_args)

    # Mock the API endpoint
    requests_mock.patch(f"{BASE_URL}/{ENDPOINTS['alert_update'].format('alert_456')}", json={"success": True})

    args = {
        "remote_incident_id": "remote_123",
        "data": {"alertid": "alert_456"},
        "inc_status": 1,  # IncidentStatus.ACTIVE
        "delta": {},
        "incident_changed": True,
    }

    result = update_remote_system_command(mock_client, args)

    # Verify the result
    assert result == "remote_123"

    # Verify the PATCH request was made with the correct payload
    history = requests_mock.request_history
    assert len(history) == 1
    assert history[0].method == "PATCH"
    assert history[0].json() == {"status": "in_progress"}


def test_update_remote_system_command_tags_update_with_platform_tags_exist(mocker, requests_mock, mock_client):
    """
    Given:
    - Valid arguments with tags in delta and incident changed
    - GTI platform has existing tags

    When:
    - Running update_remote_system_command

    Then:
    - Tags should be updated with platform case-sensitive matching via a PATCH request.
    """
    from GoogleThreatIntelligenceDTMAlerts import update_remote_system_command

    # Mock UpdateRemoteSystemArgs
    mock_args = mocker.Mock()
    mock_args.remote_incident_id = "remote_123"
    mock_args.data = {"alertid": "alert_456"}
    mock_args.inc_status = 1  # IncidentStatus.ACTIVE
    mock_args.delta = {"tags": ["test", "malware", "newtag"]}
    mock_args.incident_changed = True

    mocker.patch("GoogleThreatIntelligenceDTMAlerts.UpdateRemoteSystemArgs", return_value=mock_args)

    # Mock API endpoints
    requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_stat']}", json={"tag": [{"tag": "Test"}, {"tag": "Malware"}]})
    requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_get'].format('alert_456')}", json={"tags": ["ExistingTag"]})
    requests_mock.patch(f"{BASE_URL}/{ENDPOINTS['alert_update'].format('alert_456')}", json={"success": True})

    args = {
        "remote_incident_id": "remote_123",
        "data": {"alertid": "alert_456"},
        "inc_status": 1,  # IncidentStatus.ACTIVE
        "delta": {"tags": ["test", "malware", "newtag"]},
        "incident_changed": True,
    }

    result = update_remote_system_command(mock_client, args)

    # Verify the result
    assert result == "remote_123"

    # Verify the PATCH request was made with the correct payload
    history = requests_mock.request_history
    assert len(history) == 3
    assert history[2].method == "PATCH"
    expected_tags = ["ExistingTag", "Test", "Malware", "newtag"]
    assert history[2].json() == {"tags": expected_tags}


def test_update_remote_system_command_tags_update_with_no_duplicate_tags_update(mocker, requests_mock, mock_client):
    """
    Given:
    - Valid arguments with tags in delta that already exist in current tags

    When:
    - Running update_remote_system_command

    Then:
    - No duplicate tags should be added and no PATCH request should be sent.
    """
    from GoogleThreatIntelligenceDTMAlerts import update_remote_system_command

    # Mock UpdateRemoteSystemArgs
    mock_args = mocker.Mock()
    mock_args.remote_incident_id = "remote_123"
    mock_args.data = {"alertid": "alert_456"}
    mock_args.inc_status = 1  # IncidentStatus.ACTIVE
    mock_args.delta = {"tags": ["test", "ExistingTag"]}
    mock_args.incident_changed = True

    mocker.patch("GoogleThreatIntelligenceDTMAlerts.UpdateRemoteSystemArgs", return_value=mock_args)

    # Mock API endpoints
    requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_stat']}", json={"tag": [{"tag": "Test"}]})
    requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_get'].format('alert_456')}", json={"tags": ["Test", "ExistingTag"]})

    args = {
        "remote_incident_id": "remote_123",
        "data": {"alertid": "alert_456"},
        "inc_status": 1,  # IncidentStatus.ACTIVE
        "delta": {"tags": ["test", "ExistingTag"]},
        "incident_changed": True,
    }

    result = update_remote_system_command(mock_client, args)

    # Verify the result
    assert result == "remote_123"

    # Verify no PATCH request was made
    assert not any(req.method == "PATCH" for req in requests_mock.request_history)


def test_update_remote_system_command_incident_closed_and_tags_update(mocker, requests_mock, mock_client):
    """
    Given:
    - Valid arguments with incident status DONE and tags in delta

    When:
    - Running update_remote_system_command

    Then:
    - Both status and tags should be updated in a single PATCH request.
    """
    from GoogleThreatIntelligenceDTMAlerts import update_remote_system_command

    # Mock UpdateRemoteSystemArgs
    mock_args = mocker.Mock()
    mock_args.remote_incident_id = "remote_123"
    mock_args.data = {"alertid": "alert_456"}
    mock_args.inc_status = 2  # IncidentStatus.DONE
    mock_args.delta = {"tags": ["urgent"]}
    mock_args.incident_changed = True

    mocker.patch("GoogleThreatIntelligenceDTMAlerts.UpdateRemoteSystemArgs", return_value=mock_args)

    # Mock API endpoints
    requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_stat']}", json={"tag": [{"tag": "Urgent"}]})
    requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_get'].format('alert_456')}", json={"tags": []})
    requests_mock.patch(f"{BASE_URL}/{ENDPOINTS['alert_update'].format('alert_456')}", json={"success": True})

    args = {
        "remote_incident_id": "remote_123",
        "data": {"alertid": "alert_456"},
        "inc_status": 2,  # IncidentStatus.DONE
        "delta": {"tags": ["urgent"]},
        "incident_changed": True,
    }

    result = update_remote_system_command(mock_client, args)

    # Verify the result
    assert result == "remote_123"

    # Verify the PATCH request was made with the correct payload
    history = requests_mock.request_history
    assert len(history) == 3
    assert history[2].method == "PATCH"
    expected_update = {"status": "closed", "tags": ["Urgent"]}
    assert history[2].json() == expected_update


def test_update_remote_system_command_no_mirror_alert_id(mocker, requests_mock, mock_client):
    """
    Given:
    - Arguments with missing mirror alert ID

    When:
    - Running update_remote_system_command

    Then:
    - No update should be made and no API calls should be sent.
    """
    from GoogleThreatIntelligenceDTMAlerts import update_remote_system_command

    # Mock UpdateRemoteSystemArgs
    mock_args = mocker.Mock()
    mock_args.remote_incident_id = "remote_123"
    mock_args.data = {}  # No alertid
    mock_args.inc_status = 2
    mock_args.delta = {"tags": ["test"]}
    mock_args.incident_changed = True

    mocker.patch("GoogleThreatIntelligenceDTMAlerts.UpdateRemoteSystemArgs", return_value=mock_args)

    args = {
        "remote_incident_id": "remote_123",
        "data": {},  # No alertid
        "inc_status": 2,
        "delta": {"tags": ["test"]},
        "incident_changed": True,
    }

    result = update_remote_system_command(mock_client, args)

    # Verify the result
    assert result == "remote_123"

    # Verify no API calls were made
    assert requests_mock.call_count == 0


def test_update_remote_system_command_incident_not_changed(mocker, requests_mock, mock_client):
    """
    Given:
    - Valid arguments but incident_changed is False

    When:
    - Running update_remote_system_command

    Then:
    - No update should be made and no API calls should be sent.
    """
    from GoogleThreatIntelligenceDTMAlerts import update_remote_system_command

    # Mock UpdateRemoteSystemArgs
    mock_args = mocker.Mock()
    mock_args.remote_incident_id = "remote_123"
    mock_args.data = {"alertid": "alert_456"}
    mock_args.incident_changed = False

    mocker.patch("GoogleThreatIntelligenceDTMAlerts.UpdateRemoteSystemArgs", return_value=mock_args)

    args = {"remote_incident_id": "remote_123", "data": {"alertid": "alert_456"}, "incident_changed": False}

    result = update_remote_system_command(mock_client, args)

    # Verify the result
    assert result == "remote_123"

    # Verify no API calls were made
    assert requests_mock.call_count == 0
    assert len(requests_mock.request_history) == 0


def test_update_remote_system_command_incident_active_and_tags_update(mocker, requests_mock, mock_client):
    """
    Given:
    - Valid arguments with incident status ACTIVE and delta present

    When:
    - Running update_remote_system_command

    Then:
    - Status should not be updated (only tags if present) via a PATCH request.
    """
    from GoogleThreatIntelligenceDTMAlerts import update_remote_system_command

    # Mock UpdateRemoteSystemArgs
    mock_args = mocker.Mock()
    mock_args.remote_incident_id = "remote_123"
    mock_args.data = {"alertid": "alert_456"}
    mock_args.inc_status = 1  # IncidentStatus.ACTIVE
    mock_args.delta = {"tags": ["test"]}  # Delta present
    mock_args.incident_changed = True

    mocker.patch("GoogleThreatIntelligenceDTMAlerts.UpdateRemoteSystemArgs", return_value=mock_args)

    # Mock API endpoints
    requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_stat']}", json={"tag": [{"tag": "Test"}]})
    requests_mock.get(f"{BASE_URL}/{ENDPOINTS['alert_get'].format('alert_456')}", json={"tags": []})
    requests_mock.patch(f"{BASE_URL}/{ENDPOINTS['alert_update'].format('alert_456')}", json={"success": True})

    args = {
        "remote_incident_id": "remote_123",
        "data": {"alertid": "alert_456"},
        "inc_status": 1,  # IncidentStatus.ACTIVE
        "delta": {"tags": ["test"]},
        "incident_changed": True,
    }

    result = update_remote_system_command(mock_client, args)

    # Verify the result
    assert result == "remote_123"

    # Verify only tags were updated, not status
    history = requests_mock.request_history
    assert len(history) == 3
    assert history[2].method == "PATCH"
    expected_update = {"tags": ["Test"]}
    assert history[2].json() == expected_update


def test_update_remote_system_command_incident_reopen(mocker, requests_mock, mock_client):
    """
    Given:
    - Valid arguments with incident status ACTIVE and delta present

    When:
    - Running update_remote_system_command

    Then:
    - Status should not be updated (only tags if present) via a PATCH request.
    """
    from GoogleThreatIntelligenceDTMAlerts import update_remote_system_command

    # Mock UpdateRemoteSystemArgs
    mock_args = mocker.Mock()
    mock_args.remote_incident_id = "remote_123"
    mock_args.data = {"alertid": "alert_456"}
    mock_args.inc_status = 1  # IncidentStatus.ACTIVE
    mock_args.delta = {"closingUserId": "", "runStatus": ""}
    mock_args.incident_changed = True

    mocker.patch("GoogleThreatIntelligenceDTMAlerts.UpdateRemoteSystemArgs", return_value=mock_args)

    # Mock the API endpoint
    requests_mock.patch(f"{BASE_URL}/{ENDPOINTS['alert_update'].format('alert_456')}", json={"success": True})

    args = {
        "remote_incident_id": "remote_123",
        "data": {"alertid": "alert_456"},
        "inc_status": 1,  # IncidentStatus.ACTIVE
        "delta": {"closingUserId": "", "runStatus": ""},
        "incident_changed": True,
    }

    result = update_remote_system_command(mock_client, args)

    # Verify the result
    assert result == "remote_123"

    # Verify the PATCH request was made with the correct payload
    history = requests_mock.request_history
    assert len(history) == 1
    assert history[0].method == "PATCH"
    assert history[0].json() == {"status": "in_progress"}