Proofpoint TAP v2
Use the Proofpoint Targeted Attack Protection (TAP) integration to protect against and provide additional visibility into phishing and other malicious email attacks.
Email · Proofpoint TAP
Details
| ID | Proofpoint TAP v2 |
|---|---|
| Provider | Thoma Bravo |
| Category | |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
Proofpoint TAP
Use the Proofpoint Targeted Attack Protection (TAP) integration to protect against and provide additional visibility into phishing and other malicious email attacks.
This integration was integrated and tested with version v2 of Proofpoint TAP v2
Events Fetch Look-Back
Proofpoint’s SIEM API does not always index events the moment they occur. Indexing can lag by up to ~30 minutes, so an event that already happened may not yet be returned when the integration queries for it in real time. Without a safety mechanism, these late-indexed events can be permanently missed.
The Events Fetch Look-Back (minutes) parameter solves this by overlapping fetch cycles:
- Why it’s needed: Compensates for the SIEM API indexing delay so events that are indexed after their occurrence time are still collected.
- How it works: On every fetch cycle the integration requeries the previous N minutes. Built-in deduplication ensures events already fetched are not ingested again, so no duplicates are created.
- Recommended usage: A value of 30 minutes generally covers the typical indexing delay. Set it to 0 to disable look-back entirely.
- Existing instances: For instances that were already configured before version 1.3.0, the look-back window is rolled out gradually rather than all at once. This prevents duplicate events from being created when look-back is first applied against historical data that was already fetched. No action is required on your part — the behavior is automatic and safe.
Configure Proofpoint TAP v2 in Cortex
| Parameter | Description | Required |
|---|---|---|
| Server URL | e.g., https://tap-api-v2.proofpoint.com | True |
| Service Principal | The password refers to secret | True |
| API Version | v1 is deprecated for new instances. The current API version is v2. | False |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False | |
| Threat type | A string specifying which threat type to return. If empty, all threat types are returned. Can be “url”, “attachment”, or “messageText”. | False |
| Threat status | A string specifying which threat statuses to return. If empty, will return “active” and “cleared” threats. Can be “active”, “cleared”, or “falsePositive”. | False |
| Events to fetch | False | |
| Maximum number of incident per fetch | False | |
| First fetch time range | First fetch time range (<number> <time unit>, e.g., 1 hour, 30 minutes). Proofpoint supports a maximum 1 week fetch back. | False |
| Advanced: Raw message encoding | The character encoding to apply on the message fetched (e.g. latin-1). Advanced configuration to be used only if instructed by XSOAR Support | False |
| Events Fetch Look-Back (minutes) | The number of minutes to look back during each fetch to handle the Proofpoint SIEM API indexing delay (up to 30 minutes). When set, each fetch cycle requeries the previous N minutes to catch late-indexing events that would otherwise be missed. Duplicates are filtered automatically. Set to 0 to disable. | False |
| Fetch incidents | False | |
| Incident type | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
proofpoint-get-events
Fetches events for all clicks and messages relating to known threats within the specified time period. Details as per clicks/blocked.
Base Command
proofpoint-get-events
Input
| Argument Name | Description | Required |
|---|---|---|
| interval | A string containing an ISO8601-formatted interval. If this interval overlaps with previous requests for data, records from the previous request might be duplicated. The minimum interval is thirty seconds. The maximum interval is one hour. Examples: 2016-05-01T12:00:00Z/2016-05-01T13:00:00Z - an hour interval, beginning at noon UTC on 05-01-2016 PT30M/2016-05-01T12:30:00Z - the thirty minutes beginning at noon UTC on 05-01-2016 and ending at 12:30pm * UTC 2016-05-01T05:00:00-0700/PT30M - the same interval as above, but using -0700 as the time zone. | Optional |
| threatType | A comma-separated list of the threat types to return. If empty, all threat types are returned. The following values are accepted: “url”, “attachment”, and “messageText”. Possible values are: url, attachment, messageText. | Optional |
| threatStatus | A string specifying which threat statuses to return. If empty, active and cleared threats are returned. Can be “active”, “cleared”, “falsePositive”. Possible values are: active, cleared, falsePositive. | Optional |
| sinceTime | A string containing an ISO8601 date. It represents the start of the data retrieval period. The end of the period is determined by the current API server time rounded to the nearest minute. If JSON output is selected, the end time is included in the returned result. Example: 2016-05-01T12:00:00Z. | Optional |
| sinceSeconds | An integer representing a time window (in seconds) from the current API server time. The start of the window is the current API server time, rounded to the nearest minute, less the number of seconds provided. The end of the window is the current API server time rounded to the nearest minute. If JSON output is selected, the end time is included in the returned result. | Optional |
| eventTypes | Event types to return. Possible values: “All”, “Issues”, “Delivered Messages”, “Blocked Messages”, “Permitted Clicks”, and “Blocked Clicks”. Possible values are: All, Issues, Delivered Messages, Blocked Messages, Permitted Clicks, Blocked Clicks. Default is All. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.MessagesDelivered.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS, which is unique. |
| Proofpoint.MessagesDelivered.QID | String | The queue ID of the message within PPS. It can be used to identify the message in PPS, which is not unique. |
| Proofpoint.MessagesDelivered.ccAddresses | String | A list of email addresses contained within the CC: header, excluding any friendly names. |
| Proofpoint.MessagesDelivered.clusterId | String | The name of the PPS cluster which processed the message. |
| Proofpoint.MessagesDelivered.fromAddress | String | The email address contained in the From: header, excluding any friendly name. |
| Proofpoint.MessagesDelivered.headerCC | String | The CC header. |
| Proofpoint.MessagesDelivered.headerFrom | String | The full content of the From: header, including any friendly name. |
| Proofpoint.MessagesDelivered.headerReplyTo | String | If present, the full content of the Reply-To: header, including any friendly names. |
| Proofpoint.MessagesDelivered.impostorScore | Number | The impostor score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.malwareScore | Number | The malware score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.messageId | String | Message-ID extracted from the headers of the email message. It can be used to look up the associated message in PPS, which is not unique. |
| Proofpoint.MessagesDelivered.threatsInfoMap.threat | String | The artifact which was condemned by Proofpoint. The malicious URL, hash of the attachment threat, or email address of the impostor sender. |
| Proofpoint.MessagesDelivered.threatsInfoMap.threatId | String | The unique identifier associated with this threat. It can be used to query the forensics and campaign endpoints. |
| Proofpoint.MessagesDelivered.threatsInfoMap.threatStatus | String | The current state of the threat (active, expired, false-positive, cleared). |
| Proofpoint.MessagesDelivered.threatsInfoMap.threatTime | Date | The time Proofpoint assigned the threatStatus (ISO8601 format). |
| Proofpoint.MessagesDelivered.threatsInfoMap.threatType | String | Whether the threat was an attachment, URL, or message type. |
| Proofpoint.MessagesDelivered.threatsInfoMap.threatUrl | String | A link to the entry about the threat on the TAP Dashboard. |
| Proofpoint.MessagesDelivered.messageTime | Date | The time the message was delivered to the user or quarantined by PPS. |
| Proofpoint.MessagesDelivered.modulesRun | String | The list of PPS modules that processed the message. |
| Proofpoint.MessagesDelivered.phishScore | Number | The phishing score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.policyRoutes | String | The policy routes that the message matched during processing by PPS. |
| Proofpoint.MessagesDelivered.quarantineFolder | String | The name of the folder that contains the quarantined message. This appears only for messagesBlocked. |
| Proofpoint.MessagesDelivered.quarantineRule | String | The name of the rule that quarantined the message. This appears only for messagesBlocked events. |
| Proofpoint.MessagesDelivered.recipient | String | A list containing the email addresses of the recipients. |
| Proofpoint.MessagesDelivered.replyToAddress | String | The email address contained in the Reply-To: header, excluding any friendly name. |
| Proofpoint.MessagesDelivered.sender | String | The email address of the SMTP (envelope) sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.MessagesDelivered.senderIP | String | The IP address of the sender. |
| Proofpoint.MessagesDelivered.spamScore | Number | The spam score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.subject | String | The subject line of the message, if available. |
| Proofpoint.MessagesBlocked.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS, which is unique. |
| Proofpoint.MessagesBlocked.QID | String | The queue ID of the message within PPS. It can be used to identify the message in PPS, which is not unique. |
| Proofpoint.MessagesBlocked.ccAddresses | String | A list of email addresses contained within the CC: header, excluding any friendly names. |
| Proofpoint.MessagesBlocked.clusterId | String | The name of the PPS cluster that processed the message. |
| Proofpoint.MessagesBlocked.fromAddress | String | The email address contained in the From: header, excluding any friendly name. |
| Proofpoint.MessagesBlocked.headerCC | String | The CC header. |
| Proofpoint.MessagesBlocked.headerFrom | String | The full content of the From: header, including any friendly name. |
| Proofpoint.MessagesBlocked.headerReplyTo | String | If present, the full content of the Reply-To: header, including any friendly names. |
| Proofpoint.MessagesBlocked.impostorScore | Number | The impostor score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.malwareScore | Number | The malware score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.messageId | String | Message-ID extracted from the headers of the email message. It can be used to look up the associated message in PPS, which is not unique. |
| Proofpoint.MessagesBlocked.threatsInfoMap.threat | String | The artifact which was condemned by Proofpoint. The malicious URL, hash of the attachment threat, or email address of the impostor sender. |
| Proofpoint.MessagesBlocked.threatsInfoMap.threatId | String | The unique identifier associated with this threat. It can be used to query the forensics and campaign endpoints. |
| Proofpoint.MessagesBlocked.threatsInfoMap.threatStatus | String | The current state of the threat (active, expired, false-positive, cleared). |
| Proofpoint.MessagesBlocked.threatsInfoMap.threatTime | Date | The time Proofpoint assigned the threatStatus (ISO8601 format). |
| Proofpoint.MessagesBlocked.threatsInfoMap.threatType | String | Whether the threat was an attachment, URL, or message type. |
| Proofpoint.MessagesBlocked.threatsInfoMap.threatUrl | String | A link to the entry about the threat on the TAP dashboard. |
| Proofpoint.MessagesBlocked.messageTime | Date | The time the message was blocked to the user or quarantined by PPS. |
| Proofpoint.MessagesBlocked.messageTime | String | The list of PPS modules that processed the message. |
| Proofpoint.MessagesBlocked.modulesRun | String | The list of PPS modules that processed the message. |
| Proofpoint.MessagesBlocked.phishScore | Number | The phishing score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.policyRoutes | String | The policy routes that the message matched during processing by PPS. |
| Proofpoint.MessagesBlocked.quarantineFolder | String | The name of the folder that contains the quarantined message. This appears only for messagesBlocked. |
| Proofpoint.MessagesBlocked.quarantineRule | String | The name of the rule that quarantined the message. This appears only for messagesBlocked events. |
| Proofpoint.MessagesBlocked.recipient | String | A list containing the email addresses of the recipients. |
| Proofpoint.MessagesBlocked.replyToAddress | String | The email address contained in the Reply-To: header, excluding any friendly name. |
| Proofpoint.MessagesBlocked.sender | String | The email address of the SMTP (envelope) sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.MessagesBlocked.senderIP | String | The IP address of the sender. |
| Proofpoint.MessagesBlocked.spamScore | Number | The spam score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.subject | String | The subject line of the message, if available. |
| Proofpoint.ClicksPermitted.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS, which is unique. |
| Proofpoint.ClicksPermitted.campaignId | String | An identifier for the campaign of which the threat is a member, if available at the time of the query. Threats can be linked to campaigns even after these events are retrieved. |
| Proofpoint.ClicksPermitted.classification | String | The threat category of the malicious URL. |
| Proofpoint.ClicksPermitted.clickIP | String | The external IP address of the user who clicked the link. If the user is behind a firewall performing network address translation, the IP address of the firewall will be shown. |
| Proofpoint.ClicksPermitted.clickTime | Date | The time the user clicked the URL. |
| Proofpoint.ClicksPermitted.messageID | String | The Message-ID extracted from the headers of the email message. It can be used to look up the associated message in PPS and is not unique. |
| Proofpoint.ClicksPermitted.recipient | String | The email address of the recipient. |
| Proofpoint.ClicksPermitted.sender | String | The email address of the sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.ClicksPermitted.senderIP | String | The IP address of the sender. |
| Proofpoint.ClicksPermitted.threatID | String | The unique identifier associated with this threat. It can be used to query the forensics and campaign endpoints. |
| Proofpoint.ClicksPermitted.threatTime | Date | The time Proofpoint identified the URL as a threat. |
| Proofpoint.ClicksPermitted.threatURL | String | A link to the entry on the TAP Dashboard for the particular threat. |
| Proofpoint.ClicksPermitted.url | String | The malicious URL which was clicked. |
| Proofpoint.ClicksPermitted.userAgent | String | The User-Agent header from the clicker’s HTTP request. |
| Proofpoint.ClicksBlocked.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS and is guaranteed to be unique. |
| Proofpoint.ClicksBlocked.campaignId | String | An identifier for the campaign of which the threat is a member, if available at the time of the query. Threats can be linked to campaigns even after these events are retrieved. |
| Proofpoint.ClicksBlocked.classification | String | The threat category of the malicious URL. |
| Proofpoint.ClicksBlocked.clickIP | String | The external IP address of the user who clicked the link. If the user is behind a firewall performing network address translation, the IP address of the firewall will be shown. |
| Proofpoint.ClicksBlocked.clickTime | Date | The time the user clicked the URL. |
| Proofpoint.ClicksBlocked.messageID | String | Message-ID extracted from the headers of the email message. It can be used to look up the associated message in PPS and is not unique. |
| Proofpoint.ClicksBlocked.recipient | String | The email address of the recipient. |
| Proofpoint.ClicksBlocked.sender | String | The email address of the sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.ClicksBlocked.senderIP | String | The IP address of the sender. |
| Proofpoint.ClicksBlocked.threatID | String | The unique identifier associated with this threat. It can be used to query the forensics and campaign endpoints. |
| Proofpoint.ClicksBlocked.threatTime | Date | The time Proofpoint identified the URL as a threat. |
| Proofpoint.ClicksBlocked.threatURL | String | A link to the entry on the TAP dashboard for the particular threat. |
| Proofpoint.ClicksBlocked.url | String | The malicious URL that was clicked. |
| Proofpoint.ClicksBlocked.userAgent | String | The User-Agent header from the clicker’s HTTP request. |
Command Example
!proofpoint-get-events interval="2021-06-07T02:00:00Z/2021-06-07T03:00:00Z"
Context Example
{
"Proofpoint": {
"ClicksBlocked": null,
"ClicksPermitted": null,
"MessagesBlocked": [
{
"GUID": "9JRzwqiZEzBesdfnEM48ItsowO9ZJ1jmBbo",
"QID": "3901vhsdfsdfg0q5d-1",
"ccAddresses": [],
"cluster": "hosted",
"completelyRewritten": false,
"fromAddress": [
"xxxx@xxx.com"
],
"headerFrom": "\"xxxx@xxx.com\" <xxxx@xxx.com>",
"headerReplyTo": null,
"id": "867899c4-bbbvnvde-9948-fxv0a2-740c13aafb98",
"impostorScore": 0,
"malwareScore": 0,
"messageID": "<98fd30b9-b15b-b883-ca4xcvxvc8-3a0dsfsf766719bc4@xxxx@xxx.com>",
"messageParts": [
{
"contentType": "text/html",
"disposition": "inline",
"filename": "text.html",
"md5": "af671999d59182d8e66e100d4140b577",
"oContentType": "text/html",
"sandboxStatus": null,
"sha256": "99e2546be00c1c2a763a51861dfgf6b2981871051843dc18542ba1417b0b464c00f"
}
],
"messageSize": 3684,
"messageTime": "2021-06-07T01:50:00.000Z",
"modulesRun": [
"av",
"spf",
"dkimv",
"spam",
"dmarc",
"pdr",
"urldefense"
],
"phishScore": 100,
"policyRoutes": [
"default_inbound"
],
"quarantineFolder": "Phish",
"quarantineRule": "inbound_spam_phish",
"recipient": [
"xxxx@xxx.com"
],
"replyToAddress": [],
"sender": "xxxx@xxx.com",
"senderIP": "000.000.000.000",
"spamScore": 100,
"subject": "Your mailbox is full......",
"threatsInfoMap": [
{
"campaignID": null,
"classification": "phish",
"threat": "io/login/verify",
"threatID": "9a53601a616eb78609e525sdfsdfc0f73356c3d9ff80f00e782105ff08c53ee5a3cfca",
"threatStatus": "active",
"threatTime": "2021-06-07T00:47:12.000Z",
"threatType": "url",
"threatUrl": "https://threatinsight.proofpoint.com"
}
],
"toAddresses": [
"xxxx@xxx.com"
],
"xmailer": null
}
],
"MessagesDelivered": null
}
}
Human Readable Output
Proofpoint Events
clicksBlocked clicksPermitted messagesBlocked messagesDelivered queryEndTime {‘spamScore’: 100, ‘phishScore’: 100, ‘threatsInfoMap’: [{‘threatID’: ‘9a53601a616eb78609e525c0f73356c3d9ff80f00e782105ff08c53ee5a3cfca’, ‘threatStatus’: ‘active’, ‘classification’: ‘phish’, ‘threatUrl’: ‘https://threatinsight.proofpoint.com’, ‘threatTime’: ‘2021-06-07T00:47:12.000Z’, ‘threat’: ‘storage.libertychurch9848737878.io/login/verify’, ‘campaignID’: None, ‘threatType’: ‘url’}, {‘threatID’: ‘b72f9ac2cec86c5f2fb795ea47f2aea23d402fe46c5c64e2565363464b1b0eb2’, ‘threatStatus’: ‘active’, ‘classification’: ‘phish’, ‘threatUrl’: ‘https://threatinsight.proofpoint.com/1c863185-589c-ad2d-49cb-0020fe555aae/threat/email/b72f9ac2cec86c5f2fb795ea47f2aea23d402fe46c5c64e2565363464b1b0eb2’, ‘threatTime’: ‘2021-06-07T00:47:23.000Z’, ‘threat’: ‘libertychurch9848737878.io’, ‘campaignID’: None, ‘threatType’: ‘url’}, {‘threatID’: ‘da0ba8d6a9d5111900f5927eb4554e49fd30e6c5c4ad5b0c975feeb19c3bfc5b’, ‘threatStatus’: ‘active’, ‘classification’: ‘phish’, ‘threatUrl’: ‘https://threatinsight.proofpoint.com/1c863185-589c-ad2d-49cb-0020fe555aae/threat/email/da0ba8d6a9d5111900f5927eb4554e49fd30e6c5c4ad5b0c975feeb19c3bfc5b’, ‘threatTime’: ‘2021-06-07T00:47:22.000Z’, ‘threat’: ‘storage.libertychurch9848737878.io/login/’, ‘campaignID’: None, ‘threatType’: ‘url’}], ‘messageTime’: ‘2021-06-07T01:50:00.000Z’, ‘impostorScore’: 0.0, ‘malwareScore’: 0, ‘cluster’: ‘hosted’, ‘subject’: ‘Your mailbox is full……’, ‘quarantineFolder’: ‘Phish’, ‘quarantineRule’: ‘inbound_spam_phish’, ‘policyRoutes’: [‘default_inbound’], ‘modulesRun’: [‘av’, ‘spf’, ‘dkimv’, ‘spam’, ‘dmarc’, ‘pdr’, ‘urldefense’], ‘messageSize’: 3684, ‘headerFrom’: ‘“xxxx@xxx.com” xxxx@xxx.com’, ‘headerReplyTo’: None, ‘fromAddress’: [‘xxxx@xxx.com’], ‘ccAddresses’: [], ‘replyToAddress’: [], ‘toAddresses’: [‘xxxx@xxx.com’], ‘xmailer’: None, ‘messageParts’: [{‘disposition’: ‘inline’, ‘sha256’: ‘99e2546be00c1c2a763a51861f6b29818710dsfsdf51843dc18542ba1417b0b464c00f’, ‘md5’: ‘af671999d59182d8e66e100d4140b577’, ‘filename’: ‘text.html’, ‘sandboxStatus’: None, ‘oContentType’: ‘text/html’, ‘contentType’: ‘text/html’}], ‘completelyRewritten’: False, ‘id’: ‘867899c4-bbde-9948-f0a2-740c13aafb98’, ‘QID’: ‘3901vhsdvf0q5d-1’, ‘GUID’: ‘9JRzwqisvsdvZEzBenEM48ItsowO9ZJ1jmBbo’, ‘sender’: ‘xxxx@xxx.com’, ‘recipient’: [‘xxxx@xxx.com’], ‘senderIP’: ‘000.000.000.000’, ‘messageID’: ‘xxxx@xxx.com’}
proofpoint-get-forensics
Returns forensics evidence.
Base Command
proofpoint-get-forensics
Input
| Argument Name | Description | Required |
|---|---|---|
| threatId | The ID of the threat (use with either threatId or campaignId). | Optional |
| campaignId | ID of the campaign (use with either threatId or campaignId). | Optional |
| includeCampaignForensics | Whether to include forensic evidence for the whole campaign. Can be used with threatId only. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.Report.ID | String | The ID of the report. |
| Proofpoint.Report.Type | String | The threat type. Can be: “attachment”, “url”, or “hybrid”. |
| Proofpoint.Report.Scope | String | Whether the report scope covers a campaign or an individual threat. |
| Proofpoint.Report.Attachment.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Attachment.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Attachment.Display | String | A friendly display string. |
| Proofpoint.Report.Attachment.SHA256 | String | The SHA256 hash of the attachment’s contents. |
| Proofpoint.Report.Attachment.MD5 | String | The MD5 hash of the attachment’s contents. |
| Proofpoint.Report.Attachment.Blacklisted | Number | Optional. Whether the file was block listed. |
| Proofpoint.Report.Attachment.Offset | Number | Optional. The offset in bytes where the malicious content was found. |
| Proofpoint.Report.Attachment.Size | Number | Optional. The size in bytes of the attachment’s contents. |
| Proofpoint.Report.Attachment.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Attachment.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Attachment.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Cookie.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Cookie.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Cookie.Display | String | A friendly display string. |
| Proofpoint.Report.Cookie.Action | String | Whether the cookie was set or deleted. |
| Proofpoint.Report.Cookie.Domain | String | The domain that set the cookie. |
| Proofpoint.Report.Cookie.Key | String | The name of the cookie being set or deleted. |
| Proofpoint.Report.Cookie.Value | String | Optional. The content of the cookie being set. |
| Proofpoint.Report.Cookie.Platform.Name | String | Name of the platform. |
| Proofpoint.Report.Cookie.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Cookie.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.DNS.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.DNS.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.DNS.Display | String | A friendly display string. |
| Proofpoint.Report.DNS.Host | String | The hostname being resolved. |
| Proofpoint.Report.DNS.CNames | String | Optional. An array of CNames, which were associated with the hostname. |
| Proofpoint.Report.DNS.IP | String | Optional. An array of IP addresses that were resolved to the hostname. |
| Proofpoint.Report.DNS.NameServers | String | Optional. The nameservers responsible for the hostname’s domain. |
| Proofpoint.Report.DNS.NameServersList | String | Optional. The nameservers responsible for the hostnames. |
| Proofpoint.Report.DNS.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.DNS.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.DNS.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Dropper.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Dropper.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Dropper.Display | String | A friendly display string. |
| Proofpoint.Report.Dropper.Path | String | The location of the dropper file. |
| Proofpoint.Report.Dropper.URL | String | Optional. The name of the static rule inside the sandbox that identified the dropper. |
| Proofpoint.Report.Dropper.Rule | String | Optional. The URL the dropper contacted. |
| Proofpoint.Report.Dropper.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Dropper.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Dropper.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.File.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.File.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.File.Display | String | A friendly display string. |
| Proofpoint.Report.File.Path | String | Optional. The location of the file operated on. |
| Proofpoint.Report.File.Action | String | Optional. The filesystem call made (create, modify, or delete). |
| Proofpoint.Report.File.Rule | String | Optional. The name of the static rule inside the sandbox that identified the suspicious file. |
| Proofpoint.Report.File.SHA256 | Unknown | Optional. The SH256 hash of the file’s contents. |
| Proofpoint.Report.File.MD5 | String | Optional. The MD5 hash of the file’s contents. |
| Proofpoint.Report.File.Size | Number | Optional. The size in bytes of the file’s contents. |
| Proofpoint.Report.File.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.File.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.File.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.IDS.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.IDS.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.IDS.Display | String | A friendly display string. |
| Proofpoint.Report.IDS.Name | String | The friendly name of the IDS rule that observed the malicious traffic. |
| Proofpoint.Report.IDS.SignatureID | String | The identifier of the IDS rule that observed the malicious traffic. |
| Proofpoint.Report.IDS.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.IDS.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.IDS.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Mutex.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Mutex.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Mutex.Display | String | A friendly display string. |
| Proofpoint.Report.Mutex.Name | String | The name of the mutex. |
| Proofpoint.Report.Mutex.Path | String | Optional. The path to the process which spawned the mutex. |
| Proofpoint.Report.Mutex.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Mutex.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Mutex.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Network.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Network.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Network.Display | String | A friendly display string. |
| Proofpoint.Report.Network.Action | String | The type of network activity being initiated (connect or listen). |
| Proofpoint.Report.Network.IP | String | The remote IP address being contacted. |
| Proofpoint.Report.Network.Port | String | The remote IP port being contacted. |
| Proofpoint.Report.Network.Type | String | The protocol being used (tcp or udp). |
| Proofpoint.Report.Network.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Network.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Network.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Process.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Process.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Process.Display | String | A friendly display string. |
| Proofpoint.Report.Process.Action | String | The action performed on the process. Relevant when create is produced. |
| Proofpoint.Report.Process.Path | String | The location of the executable that spawned the process. |
| Proofpoint.Report.Process.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Process.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Process.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Registry.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Registry.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Registry.Display | String | A friendly display string. |
| Proofpoint.Report.Registry.Name | String | Optional. The name of the registry entry being created or set. |
| Proofpoint.Report.Registry.Action | String | The registry change made (create or set). |
| Proofpoint.Report.Registry.Key | String | The location of the registry key being modified. |
| Proofpoint.Report.Registry.Value | String | Optional. The contents of the key being created or set. |
| Proofpoint.Report.Registry.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Registry.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Registry.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.URL.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.URL.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.URL.Display | String | A friendly display string. |
| Proofpoint.Report.URL.URL | String | The URL which was observed. |
| Proofpoint.Report.URL.Blacklisted | Boolean | Optional. Whether the URL appeared on a block list. |
| Proofpoint.Report.URL.SHA256 | String | Optional. The SHA256 hash of the file downloaded from the URL. |
| Proofpoint.Report.URL.MD5 | String | Optional. The MD5 hash of the file downloaded from the URL. |
| Proofpoint.Report.URL.Size | Number | Optional. The size in bytes of the file retrieved from the URL. |
| Proofpoint.Report.URL.HTTPStatus | Number | Optional. The HTTP status code that was produced when our sandbox visited the URL. |
| Proofpoint.Report.URL.IP | String | Optional. The IP address that was resolved to the hostname by the sandbox. |
| Proofpoint.Report.URL.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.URL.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.URL.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Behavior.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Behavior.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Behavior.Display | String | A friendly display string. |
| Proofpoint.Report.Behavior.URL | String | The URL that was observed. |
| Proofpoint.Report.Behavior.Path | String | The location of the executable which spawned the behavior. |
| Proofpoint.Report.Behavior.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Behavior.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Behavior.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Behavior.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Behavior.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Behavior.Display | String | A friendly display string. |
| Proofpoint.Report.Behavior.URL | String | The URL that was observed. |
| Proofpoint.Report.Behavior.Path | String | The location of the executable that spawned the behavior. |
| Proofpoint.Report.Behavior.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Behavior.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Behavior.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Screenshot.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Screenshot.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Screenshot.Display | String | A friendly display string. |
| Proofpoint.Report.Screenshot.URL | String | The URL hosting the screenshot image. |
Command Example
!proofpoint-get-forensics campaignId="35e291e1-c9da-4ebd-b229-538bf759b546"
Context Example
{
"Proofpoint": {
"Report": {
"Attachment": [
{
"Display": "Malicious attachment with SHA-256: 1c207a1ea4b89cc63c2d8391afcf25",
"Malicious": true,
"Platform": [
{
"Name": "Win10",
"OS": "win",
"Version": "win10"
}
],
"SHA256": "1c207da4b89cc63c2d8391afcf25",
"Time": 0
}
]
}
}
}
Human Readable Output
Forensic results from ProofPoint for ID: 35e291e1-c9da-4ebd-b229-538bf759b546
ID Scope Type 35e291e1-c9da-4ebd-b229-538bf759b546 CAMPAIGN
proofpoint-get-events-clicks-blocked
Gets events for clicks to malicious URLs blocked in the specified time period. Must provide either the interval or time_range arguments.
Base Command
proofpoint-get-events-clicks-blocked
Input
| Argument Name | Description | Required |
|---|---|---|
| threat_status | Click’s threat status to be retrieved. If no value is specified, active and cleared threats will be retrieved. Possible values: ‘active’, ‘cleared’, and ‘falsePositive’. Possible values are: active, cleared, falsePositive. | Optional |
| interval | ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one hour. For example: 2021-04-27T09:00:00Z/2021-04-27T10:00:00Z. | Optional |
| time_range | Represents the start of the data retrieval period. For example: 1 week, 2 days, 3 hours, etc. The maximum is 1 week. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.ClicksBlocked.url | String | The malicious URL was clicked. |
| Proofpoint.ClicksBlocked.classification | String | The threat category of the malicious URL (Malware, Phish, or Spam) |
| Proofpoint.ClicksBlocked.clickTime | Date | The time the user clicked the URL. |
| Proofpoint.ClicksBlocked.threatTime | Date | The time that Proofpoint identified the URL as a threat. |
| Proofpoint.ClicksBlocked.userAgent | String | The User-Agent header from the clicker’s HTTP request. |
| Proofpoint.ClicksBlocked.campaignId | String | An identifier for the campaign of which the threat is a member. |
| Proofpoint.ClicksBlocked.id | String | The unique ID of the click. |
| Proofpoint.ClicksBlocked.clickIP | String | The external IP address of the user who clicked the link. |
| Proofpoint.ClicksBlocked.sender | String | The email address of the sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.ClicksBlocked.recipient | String | The email address of the recipient. |
| Proofpoint.ClicksBlocked.senderIP | String | The IP address of the sender. |
| Proofpoint.ClicksBlocked.threatID | String | The unique identifier associated with this threat. |
| Proofpoint.ClicksBlocked.threatURL | String | A link to the entry on the TAP dashboard for the particular threat. |
| Proofpoint.ClicksBlocked.threatStatus | String | The current state of the threat. |
| Proofpoint.ClicksBlocked.messageID | String | The ID of the message that the URL belongs to. |
| Proofpoint.ClicksBlocked.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS. |
Command Example
!proofpoint-get-events-clicks-blocked time_range="1 hour"
Context Example
{
"Proofpoint": {
"ClicksBlocked": {
"campaignId": "46e01b8a-c899-404d-bcd9-189bb393d1a7",
"classification": "MALWARE",
"clickIP": "192.0.2.2",
"clickTime": "2010-01-22T00:00:10.000Z",
"messageID": "4444",
"recipient": "xxxx@xxx.com",
"sender": "xxxx@xxx.com",
"senderIP": "000.000.000.000",
"threatID": "threat_num2",
"threatTime": "2010-01-22T00:00:20.000Z",
"threatURL": "https://threatinsight.proofpoint.com",
"url": "http://badguy.zz/",
"userAgent": "Mozilla/5.0(WindowsNT6.1;WOW64;rv:27.0)Gecko/20100101Firefox/27.0"
}
}
}
Human Readable Output
Blocked Clicks
Id Sender IP Recipient Classification Threat ID Threat URL Threat Status Threat Time Click Time Campaign Id User Agent 000.000.000.000 xxxx@xxx.com MALWARE threat_num2 https://threatinsight.proofpoint.com 2010-01-22T00:00:20.000Z 2010-01-22T00:00:10.000Z 46e01b8a-c899-404d-bcd9-189bb393d1a7 Mozilla/5.0(WindowsNT6.1;WOW64;rv:27.0)Gecko/20100101Firefox/27.0
proofpoint-get-events-clicks-permitted
Get events for clicks to malicious URLs permitted in the specified time period. Must provide either the interval or time_range arguments.
Base Command
proofpoint-get-events-clicks-permitted
Input
| Argument Name | Description | Required |
|---|---|---|
| threat_status | Click’s threat status to be retrieved. If no value is specified, active and cleared threats will be retrieved. Possible values: ‘active’, ‘cleared’, and ‘falsePositive’. Possible values are: active, cleared, falsePositive. | Optional |
| interval | ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one hour. For example: 2021-04-27T09:00:00Z/2021-04-27T10:00:00Z. | Optional |
| time_range | Represents the start of the data retrieval period. For example: 1 week, 2 days, 3 hours, etc. The maximum is 1 week. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.ClicksPermitted.url | String | The malicious URL that was clicked. |
| Proofpoint.ClicksPermitted.classification | String | The threat category of the malicious URL (Malware, Phish, or Spam). |
| Proofpoint.ClicksPermitted.clickTime | Date | The time the user clicked the URL. |
| Proofpoint.ClicksPermitted.threatTime | Date | The time that Proofpoint identified the URL as a threat. |
| Proofpoint.ClicksPermitted.userAgent | String | The User-Agent header from the clicker’s HTTP request. |
| Proofpoint.ClicksPermitted.campaignId | String | An identifier for the campaign of which the threat is a member. |
| Proofpoint.ClicksPermitted.id | String | The unique ID of the click. |
| Proofpoint.ClicksPermitted.clickIP | String | The external IP address of the user who clicked the link. |
| Proofpoint.ClicksPermitted.sender | String | The email address of the sender. The user-part is hashed. The domain-part is in cleartext. |
| Proofpoint.ClicksPermitted.recipient | String | The email address of the recipient. |
| Proofpoint.ClicksPermitted.senderIP | String | The IP address of the sender. |
| Proofpoint.ClicksPermitted.threatID | String | The unique identifier associated with this threat. |
| Proofpoint.ClicksPermitted.threatURL | String | A link to the entry on the TAP dashboard for the particular threat. |
| Proofpoint.ClicksPermitted.threatStatus | String | The current state of the threat. |
| Proofpoint.ClicksPermitted.messageID | String | The ID of the message that the URL belongs to. |
| Proofpoint.ClicksPermitted.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS. |
Command Example
!proofpoint-get-events-clicks-permitted time_range="1 hour"
Context Example
{
"Proofpoint": {
"ClicksPermitted": {
"campaignId": "46e01b8a-c899-404d-bcd9-189bb393d1a7",
"classification": "MALWARE",
"clickIP": "192.0.2.2",
"clickTime": "2010-01-22T00:00:10.000Z",
"messageID": "4444",
"recipient": "xxxx@xxx.com",
"sender": "9facbf452def2d7efc5b5c48cdb837fa@badguy.zz",
"senderIP": "000.000.000.000",
"threatID": "threat_num2",
"threatTime": "2010-01-22T00:00:20.000Z",
"threatURL": "https://threatinsight.proofpoint.com",
"url": "http://badguy.zz/",
"userAgent": "Mozilla/5.0(WindowsNT6.1;WOW64;rv:27.0)Gecko/20100101Firefox/27.0"
}
}
}
Human Readable Output
Permitted Clicks
Id Sender IP Recipient Classification Threat ID Threat URL Threat Status Threat Time Click Time Campaign Id User Agent 192.0.2.255 xxxx@xxx.com MALWARE threat_num2 https://threatinsight.proofpoint.com 2010-01-22T00:00:20.000Z 2010-01-22T00:00:10.000Z 46e01b8a-c899-404d-bcd9-189bb393d1a7 Mozilla/5.0(WindowsNT6.1;WOW64;rv:27.0)Gecko/20100101Firefox/27.0
proofpoint-get-events-messages-blocked
Get events for blocked messages in the specified time period. Must provide either the interval or time_range arguments.
Base Command
proofpoint-get-events-messages-blocked
Input
| Argument Name | Description | Required |
|---|---|---|
| threat_type | Message’s threat type to be retrieved. If no value is specified, all threat types will be retrieved. Possible values: ‘url’, ‘attachment’, and ‘message’. Possible values are: url, attachment, message. | Optional |
| threat_status | Message’s threat status to be retrieved. If no value is specified, active and cleared threats will be retrieved. Possible values: ‘active’, ‘cleared’, and ‘falsePositive’. Possible values are: active, cleared, falsePositive. | Optional |
| interval | ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one hour. For example: 2021-04-27T09:00:00Z/2021-04-27T10:00:00Z. | Optional |
| time_range | Represents the start of the data retrieval period. For example: 1 week, 2 days, 3 hours, etc. The maximum is 1 week. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.MessagesBlocked.spamScore | Number | The spam score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.phishScore | Number | The phish score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.threatsInfoMap | List | List that contains details about detected threats within the message. Contains: campaignID, classification, threat, threatID, threatStatus,threatTime, threatType, threatUrl. |
| Proofpoint.MessagesBlocked.messageTime | Date | The time the message was delivered to the user or quarantined by PPS. |
| Proofpoint.MessagesBlocked.impostorScore | Number | The impostor score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.malwareScore | Number | The malware score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.cluster | String | The name of the PPS cluster that processed the message. |
| Proofpoint.MessagesBlocked.subject | String | The subject line of the message, if available. |
| Proofpoint.MessagesBlocked.quarantineFolder | String | The name of the folder that contains the quarantined message. This appears only for blocked messages. For delivered messages will be ‘None’. |
| Proofpoint.MessagesBlocked.quarantineRule | String | The name of the rule that quarantined the message. This appears only for messagesBlocked events. |
| Proofpoint.MessagesBlocked.policyRoutes | List | The policy routes that the message matched during processing by PPS. |
| Proofpoint.MessagesBlocked.modulesRun | String | The list of PPS modules that processed the message. |
| Proofpoint.MessagesBlocked.messageSize | Number | The size in bytes of the message, including headers and attachments. |
| Proofpoint.MessagesBlocked.Header.headerFrom | String | The full content of the From header, including any friendly name. |
| Proofpoint.MessagesBlocked.Header.headerReplyTo | String | If present, the full content of the Reply-To: header, including any friendly names. |
| Proofpoint.MessagesBlocked.Header.fromAddress | List | The email address contained in the From header, excluding the friendly name. |
| Proofpoint.MessagesBlocked.Header.ccAddresses | List | A list of email addresses contained within the CC: header, excluding friendly names. |
| Proofpoint.MessagesBlocked.Header.replyToAddress | List | The email address contained in the Reply-To: header, excluding friendly name. |
| Proofpoint.MessagesBlocked.Header.toAddresses | List | A list of email addresses contained within the To: header, excluding friendly names. |
| Proofpoint.MessagesBlocked.Header.xmailer | String | The content of the X-Mailer: header, if present. |
| Proofpoint.MessagesBlocked.messageParts | List | An array of structures that contain details about parts of the message, including both message bodies and attachments. |
| Proofpoint.MessagesBlocked.completelyRewritten | String | The rewrite status of the message. If value is true, all instances of URL threats within the message were successfully rewritten. If the value is false, at least one instance of the threat URL was not rewritten. If the value is ‘na’, the message did not contain any URL-based threats. |
| Proofpoint.MessagesBlocked.id | String | The unique ID of the message. |
| Proofpoint.MessagesBlocked.sender | String | The email address of the SMTP (envelope) sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.MessagesBlocked.recipient | List | A list containing the email addresses of the recipients. |
| Proofpoint.MessagesBlocked.senderIP | String | The IP address of the sender. |
| Proofpoint.MessagesBlocked.messageID | String | Message-ID extracted from the headers of the email message. |
| Proofpoint.MessagesBlocked.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS. |
Command Example
!proofpoint-get-events-messages-blocked interval="2021-06-07T02:00:00Z/2021-06-07T03:00:00Z"
Context Example
{
"Proofpoint": {
"MessagesBlocked": [
{
"GUID": "9JRzwqiZEzBenEMsdgsdfg48ItsowO9ZJ1jmBbo",
"Header": {
"ccAddresses": [],
"fromAddress": [
"xxxx@xxx.com"
],
"headerFrom": "\"xxxx@xxx.com\" <xxxx@xxx.com>",
"headerReplyTo": null,
"replyToAddress": [],
"toAddresses": [
"xxxx@xxx.com"
],
"xmailer": null
},
"cluster": "hosted",
"completelyRewritten": false,
"id": "867899c4-bbde-9948-f0a2-740c13aafb98",
"impostorScore": 0,
"malwareScore": 0,
"messageID": "<xxxx@xxx.com>",
"messageParts": [
{
"contentType": "text/html",
"disposition": "inline",
"filename": "text.html",
"md5": "a",
"oContentType": "text/html",
"sandboxStatus": null,
"sha256": "99843dc18542ba1417b0b464c00f"
}
],
"messageSize": 3684,
"messageTime": "2021-06-07T01:50:00.000Z",
"modulesRun": [
"av",
"spf",
"dkimv",
"spam",
"dmarc",
"pdr",
"urldefense"
],
"phishScore": 100,
"policyRoutes": [
"default_inbound"
],
"quarantineFolder": "Phish",
"quarantineRule": "inbound_spam_phish",
"recipient": [
"xxxx@xxx.com"
],
"sender": "xxxx@xxx.com",
"senderIP": "000.000.000.000",
"spamScore": 100,
"subject": "Your mailbox is full......",
"threatsInfoMap": [
{
"campaignID": null,
"classification": "phish",
"threat": "login/verify",
"threatID": "9a",
"threatStatus": "active",
"threatTime": "2021-06-07T00:47:12.000Z",
"threatType": "url",
"threatUrl": "https://threatinsight.proofpoint.com"
},
]
}
]
}
}
Human Readable Output
Blocked Messages
Sender IP Sender Recipient Subject Message Size Message Time Malware Score Phish Score Spam Score 000.000.000.000 xxxx@xxx.com xxxx@xxx.com Your mailbox is full…… 3684 2021-06-07T01:50:00.000Z 0 100 100 Blocked Messages Threats Information
Sender Recipient Subject Classification Threat Threat Status Threat Url Threat ID Threat Time Campaign ID xxxx@xxx.com xxxx@xxx.com Your mailbox is full…… phish login/verify active https://threatinsight.proofpoint.com 9a53601a616eb78609e525c0f3ee5a3cfca 2021-06-07T00:47:12.000Z
proofpoint-get-events-messages-delivered
Get events for delivered messages in the specified time period. Must provide either the interval or time_range arguments.
Base Command
proofpoint-get-events-messages-delivered
Input
| Argument Name | Description | Required |
|---|---|---|
| threat_type | Message’s threat type to be retrieved. If no value is specified, all threat types will be retrieved. Possible values: ‘url’, ‘attachment’, and ‘message’. Possible values are: url, attachment, message. | Optional |
| threat_status | Message’s threat status to be retrieved. If no value is specified, active and cleared threats will be retrieved. Possible values: ‘active’, ‘cleared’, and ‘falsePositive’. Possible values are: active, cleared, falsePositive. | Optional |
| interval | ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one hour. For example: 2021-04-27T09:00:00Z/2021-04-27T10:00:00Z. | Optional |
| time_range | Represents the start of the data retrieval period. For example: 1 week, 2 days, 3 hours, etc. The maximum is 1 week. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.MessagesDelivered.spamScore | Number | The spam score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.phishScore | Number | The phish score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.threatsInfoMap | List | List that contains details about detected threats within the message. Contains: campaignID, classification, threat, threatID, threatStatus,threatTime, threatType, threatUrl. |
| Proofpoint.MessagesDelivered.messageTime | Date | The time the message was delivered to the user or quarantined by PPS. |
| Proofpoint.MessagesDelivered.impostorScore | Number | The impostor score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.malwareScore | Number | The malware score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.cluster | String | The name of the PPS cluster that processed the message. |
| Proofpoint.MessagesDelivered.subject | String | The subject line of the message, if available. |
| Proofpoint.MessagesDelivered.quarantineFolder | String | The name of the folder that contains the quarantined message. This appears only for blocked messages. For delivered messages will be ‘None’. |
| Proofpoint.MessagesDelivered.quarantineRule | String | The name of the rule that quarantined the message. This appears only for messagesBlocked events. |
| Proofpoint.MessagesDelivered.policyRoutes | List | The policy routes that the message matched during processing by PPS. |
| Proofpoint.MessagesDelivered.modulesRun | String | The list of PPS modules that processed the message. |
| Proofpoint.MessagesDelivered.messageSize | Number | The size in bytes of the message, including headers and attachments. |
| Proofpoint.MessagesDelivered.Header.headerFrom | String | The full content of the From header, including any friendly name. |
| Proofpoint.MessagesDelivered.Header.headerReplyTo | String | If present, the full content of the Reply-To: header, including any friendly names. |
| Proofpoint.MessagesDelivered.Header.fromAddress | List | The email address contained in the From header, excluding the friendly name. |
| Proofpoint.MessagesDelivered.Header.ccAddresses | List | A list of email addresses contained within the CC: header, excluding friendly names. |
| Proofpoint.MessagesDelivered.Header.replyToAddress | List | The email address contained in the Reply-To: header, excluding friendly name. |
| Proofpoint.MessagesDelivered.Header.toAddresses | List | A list of email addresses contained within the To: header, excluding friendly names. |
| Proofpoint.MessagesDelivered.Header.xmailer | String | The content of the X-Mailer: header, if present. |
| Proofpoint.MessagesDelivered.messageParts | List | An array of structures that contains details about parts of the message, including both message bodies and attachments. |
| Proofpoint.MessagesDelivered.completelyRewritten | String | The rewrite status of the message. If value is true, all instances of URL threats within the message were successfully rewritten. If the value is false, at least one instance of the threat URL was not rewritten. If the value is ‘na’, the message did not contain any URL-based threats. |
| Proofpoint.MessagesDelivered.id | String | The unique ID of the message. |
| Proofpoint.MessagesDelivered.sender | String | The email address of the SMTP (envelope) sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.MessagesDelivered.recipient | List | A list containing the email addresses of the recipients. |
| Proofpoint.MessagesDelivered.senderIP | String | The IP address of the sender. |
| Proofpoint.MessagesDelivered.messageID | String | Message-ID extracted from the headers of the email message. |
| Proofpoint.MessagesDelivered.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS and is guaranteed to be unique. |
Command Example
!proofpoint-get-events-messages-delivered interval="2021-06-03T17:00:00Z/2021-06-03T18:00:00Z"
Context Example
{
"Proofpoint": {
"MessagesDelivered": {
"GUID": "Ggfsdfsdf",
"Header": {
"ccAddresses": [],
"fromAddress": [
"xxxx@xxx.com"
],
"headerFrom": "\"j.\" <xxxx@xxx.com>",
"headerReplyTo": null,
"replyToAddress": [],
"toAddresses": [],
"xmailer": null
},
"cluster": "hosted",
"completelyRewritten": true,
"id": "1828003vsdv05566e842",
"impostorScore": 0,
"malwareScore": 0,
"messageID": "<SI2PR0dfbvd.xxxx@xxx.com.com>",
"messageParts": [
{
"contentType": "text/html",
"disposition": "inline",
"filename": "text.html",
"md5": "fcfa9b21f43fbdf02965263c63e",
"oContentType": "text/html",
"sandboxStatus": null,
"sha256": "72d3dc7a01dfbdbe8e871536864f56bf235ba08ff259105ac"
},
],
"messageSize": 10171,
"messageTime": "2021-06-02T13:41:32.000Z",
"modulesRun": [
"av",
"spf",
"dkimv",
"spam",
"dmarc",
"urldefense"
],
"phishScore": 0,
"policyRoutes": [
"default_inbound",
"allow_relay"
],
"quarantineFolder": null,
"quarantineRule": null,
"recipient": [
"xxxx@xxx.com"
],
"sender": "xxxx@xxx.com",
"senderIP": "400.000.000",
"spamScore": 43,
"subject": "=",
"threatsInfoMap": [
{
"campaignID": null,
"classification": "phish",
"threat": "https://bit.ly",
"threatID": "45fe3b35ghkk2b8916934b6c0a536cc9b2603d03",
"threatStatus": "active",
"threatTime": "2021-06-03T07:17:11.000Z",
"threatType": "url",
"threatUrl": "https://threatinsight.proofpoint.com"
}
]
}
}
}
Human Readable Output
Delivered Messages
Sender IP Sender Recipient Subject Message Size Message Time Malware Score Phish Score Spam Score 00.000.000.0000 xxxx@xxx.com xxxx@xxx.com = 10171 2021-06-02T13:41:32.000Z 0 0 43 Delivered Messages Threats Information
Sender Recipient Subject Classification Threat Threat Status Threat Url Threat ID Threat Time Campaign ID xxxx@xxx.com xxxx@xxx.com = phish https://bit.ly active https://threatinsight.proofpoint.com 45fe3b35b7bd2adfad6dea4d305bea3e7c1a2b8gfhh03d03 2021-06-03T07:17:11.000Z
proofpoint-list-issues
Get events for clicks to malicious URLs permitted and messages delivered containing a known attachment threat within the specified time period. Must provide either the interval or time_range arguments.
Base Command
proofpoint-list-issues
Input
| Argument Name | Description | Required |
|---|---|---|
| threat_type | Event’s threat type to be retrieved. If no value is specified, all threat types will be retrieved. Possible values: ‘url’, ‘attachment’, and ‘message’. Possible values are: url, attachment, message. | Optional |
| threat_status | Event’s threat status to be retrieved.If no value is specified, active and cleared threats will be retrieved. Possible values: ‘url’, ‘attachment’, and ‘message’. Possible values are: active, cleared, falsePositive. | Optional |
| interval | ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one hour. For example: 2021-04-27T09:00:00Z/2021-04-27T10:00:00Z. | Optional |
| time_range | Represents the start of the data retrieval period. For example: 1 week, 2 days, 3 hours, etc. The maximum is 1 week. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.ClicksPermitted.url | String | The malicious URL was clicked. |
| Proofpoint.ClicksPermitted.classification | String | The threat category of the malicious URL (Malware, Phish, or Spam). |
| Proofpoint.ClicksPermitted.clickTime | Date | The time the user clicked the URL. |
| Proofpoint.ClicksPermitted.threatTime | Date | The time that Proofpoint identified the URL as a threat. |
| Proofpoint.ClicksPermitted.userAgent | String | The User-Agent header from the clicker’s HTTP request. |
| Proofpoint.ClicksPermitted.campaignId | String | An identifier for the campaign of which the threat is a member. |
| Proofpoint.ClicksPermitted.id | String | The unique ID of the click. |
| Proofpoint.ClicksPermitted.clickIP | String | The external IP address of the user who clicked the link. |
| Proofpoint.ClicksPermitted.sender | String | The email address of the sender. The user-part is hashed. The domain-part is in cleartext. |
| Proofpoint.ClicksPermitted.recipient | String | The email address of the recipient. |
| Proofpoint.ClicksPermitted.senderIP | String | The IP address of the sender. |
| Proofpoint.ClicksPermitted.threatID | String | The unique identifier associated with this threat. |
| Proofpoint.ClicksPermitted.threatURL | String | A link to the entry on the TAP dashboard for the particular threat. |
| Proofpoint.ClicksPermitted.threatStatus | String | The current state of the threat. |
| Proofpoint.ClicksPermitted.messageID | String | The ID of the message that the URL belongs to. |
| Proofpoint.ClicksPermitted.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS and is guaranteed to be unique. |
| Proofpoint.MessagesDelivered.spamScore | Number | The spam score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.phishScore | Number | The phish score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.threatsInfoMap | List | List which contain details about detected threats within the message. Contains: campaignID, classification, threat, threatID, threatStatus,threatTime, threatType, threatUrl. |
| Proofpoint.MessagesDelivered.messageTime | Date | THe time the message was delivered to the user or quarantined by PPS. |
| Proofpoint.MessagesDelivered.impostorScore | Number | The impostor score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.malwareScore | Number | The malware score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.cluster | String | The name of the PPS cluster that processed the message. |
| Proofpoint.MessagesDelivered.subject | String | The subject line of the message, if available. |
| Proofpoint.MessagesDelivered.quarantineFolder | String | The name of the folder that contains the quarantined message. This appears only for blocked messages. For delivered messages will be ‘None’. |
| Proofpoint.MessagesDelivered.quarantineRule | String | The name of the rule that quarantined the message. This appears only for messagesBlocked events. |
| Proofpoint.MessagesDelivered.policyRoutes | List | The policy routes that the message matched during processing by PPS. |
| Proofpoint.MessagesDelivered.modulesRun | String | The list of PPS modules that processed the message. |
| Proofpoint.MessagesDelivered.messageSize | Number | The size in bytes of the message, including headers and attachments. |
| Proofpoint.MessagesDelivered.Header.headerFrom | String | The full content of the From header, including any friendly name. |
| Proofpoint.MessagesDelivered.Header.headerReplyTo | String | If present, the full content of the Reply-To: header, including any friendly names. |
| Proofpoint.MessagesDelivered.Header.fromAddress | List | The email address contained in the From header, excluding any friendly name. |
| Proofpoint.MessagesDelivered.Header.ccAddresses | List | A list of email addresses contained within the CC: header, excluding any friendly names. |
| Proofpoint.MessagesDelivered.Header.replyToAddress | List | The email address contained in the Reply-To: header, excluding any friendly name. |
| Proofpoint.MessagesDelivered.Header.toAddresses | List | A list of email addresses contained within the To: header, excluding any friendly names. |
| Proofpoint.MessagesDelivered.Header.xmailer | String | The content of the X-Mailer: header, if present. |
| Proofpoint.MessagesDelivered.messageParts | List | An array of structures that contain details about parts of the message, including both message bodies and attachments. |
| Proofpoint.MessagesDelivered.completelyRewritten | String | The rewrite status of the message. If value is true, all instances of URL threats within the message were successfully rewritten. If the value is false, at least one instance of the threat URL was not rewritten. If the value is ‘na’, the message did not contain any URL-based threats. |
| Proofpoint.MessagesDelivered.id | String | The unique ID of the message. |
| Proofpoint.MessagesDelivered.sender | String | The email address of the SMTP (envelope) sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.MessagesDelivered.recipient | List | A list containing the email addresses of the recipients |
| Proofpoint.MessagesDelivered.senderIP | String | The IP address of the sender. |
| Proofpoint.MessagesDelivered.messageID | String | Message-ID extracted from the headers of the email message. |
| Proofpoint.MessagesDelivered.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS and is guaranteed to be unique. |
Command Example
!proofpoint-list-issues interval="2021-06-03T17:00:00Z/2021-06-03T18:00:00Z"
Context Example
{
"Proofpoint": {
"MessagesDelivered": {
"GUID": "Ggfsdfsdf",
"Header": {
"ccAddresses": [],
"fromAddress": [
"xxxx@xxx.com"
],
"headerFrom": "\"j.\" <xxxx@xxx.com>",
"headerReplyTo": null,
"replyToAddress": [],
"toAddresses": [],
"xmailer": null
},
"cluster": "hosted",
"completelyRewritten": true,
"id": "1828003vsdv05566e842",
"impostorScore": 0,
"malwareScore": 0,
"messageID": "<SI2PR0dfbvd.xxxx@xxx.com.com>",
"messageParts": [
{
"contentType": "text/html",
"disposition": "inline",
"filename": "text.html",
"md5": "fcfa9b21f43fbdf02965263c63e",
"oContentType": "text/html",
"sandboxStatus": null,
"sha256": "72d3dc7a01dfbdbe8e871536864f56bf235ba08ff259105ac"
},
],
"messageSize": 10171,
"messageTime": "2021-06-02T13:41:32.000Z",
"modulesRun": [
"av",
"spf",
"dkimv",
"spam",
"dmarc",
"urldefense"
],
"phishScore": 0,
"policyRoutes": [
"default_inbound",
"allow_relay"
],
"quarantineFolder": null,
"quarantineRule": null,
"recipient": [
"xxxx@xxx.com"
],
"sender": "xxxx@xxx.com",
"senderIP": "400.000.000",
"spamScore": 43,
"subject": "=",
"threatsInfoMap": [
{
"campaignID": null,
"classification": "phish",
"threat": "https://bit.ly",
"threatID": "45fe3b35ghkk2b8916934b6c0a536cc9b2603d03",
"threatStatus": "active",
"threatTime": "2021-06-03T07:17:11.000Z",
"threatType": "url",
"threatUrl": "https://threatinsight.proofpoint.com"
}
]
}
}
}
Human Readable Output
Delivered Messages
Sender IP Sender Recipient Subject Message Size Message Time Malware Score Phish Score Spam Score 00.000.000.0000 xxxx@xxx.com xxxx@xxx.com = 10171 2021-06-02T13:41:32.000Z 0 0 43 Delivered Messages Threats Information
Sender Recipient Subject Classification Threat Threat Status Threat Url Threat ID Threat Time Campaign ID xxxx@xxx.com xxxx@xxx.com = phish https://bit.ly active https://threatinsight.proofpoint.com 45fe3b35b7bd2adfad6dea4d305bea3e7c1a2b8gfhh03d03 2021-06-03T07:17:11.000Z
Permitted click from list-issues command result
No entries.
proofpoint-list-campaigns
Gets a list of IDs of campaigns active in a specified time period. Must provide either the interval or time_range arguments.
Base Command
proofpoint-list-campaigns
Input
| Argument Name | Description | Required |
|---|---|---|
| interval | ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one day. For example: 2021-04-27T09:00:00Z/2021-04-27T10:00:00Z. | Optional |
| limit | The maximum number of campaign IDs to produce in the response. Defaults to 100 and the maximum supported value is 200. Default is 100. | Optional |
| page | The page of results to return, in multiples of the specified size. Default is 1. | Optional |
| time_range | Represents the start of the data retrieval period. For example: 1 week, 2 days, 3 hours, etc. The maximum is 1 week. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.Campaigns.id | String | The campaign ID. |
| Proofpoint.Campaigns.lastUpdatedAt | String | Last updated timestamp of the campaign. |
Command Example
!proofpoint-list-campaigns interval="2021-06-01T11:00:00Z/2021-06-02T11:00:00Z"
Context Example
{
"Proofpoint": {
"Campaign": {
"id": "7c91b71fdgdfgdfg591a1ad38",
"lastUpdatedAt": "2021-06-03T13:01:57.000Z"
}
}
}
Human Readable Output
Campaigns List
Id Last Updated At 7c91b71fdgdfgdfg591a1ad38 2021-06-03T13:01:57.000Z
proofpoint-get-campaign
Gets details for a given campaign.
Base Command
proofpoint-get-campaign
Input
| Argument Name | Description | Required |
|---|---|---|
| campaign_id | ID of the required campaign. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.Campaign.info | List | The campaign information - ID,name, description, startDate, and notable. |
| Proofpoint.Campaign.actors | List | A list of actor objects. |
| Proofpoint.Campaign.families | List | A list of family objects. |
| Proofpoint.Campaign.malware | List | A list of malware objects. |
| Proofpoint.Campaign.techniques | List | A list of technique objects. |
| Proofpoint.Campaign.brands | List | A list of brand objects. |
| Proofpoint.Campaign.campaignMembers | List | A list of campaign member objects. |
Command Example
!proofpoint-get-campaign campaign_id="f3ff0874-85ef-475e-b3fe-d05f97b2ed3f"
Context Example
{
"Proofpoint": {
"Campaign": {
"actors": [],
"brands": [],
"campaignMembers": [],
"families": [
{
"id": "69a63403-f478-40f6-a4cb-3d2ffb85b98e",
"name": "Keylogger"
}
],
"info": {
"description": "Messages purporting to be e.g.\r\n\r\n* from <xxxx@xxx.com;' and subject \"Re: New Order From customer\".\r\n\r\nThese messages contain compressed executables that lead to the installation of AgentTesla with the following example configuration:\r\n\r\n<pre>C2_Email_Address: xxxx@xxx.com\r\nC2_Email_Password: \r\nC2_Email_Server: xxxx@xxx.com</pre>",
"id": "f3ff087dfgdfge-d05f97b2ed3f",
"name": "AgentTesla | Compressed Executables | \"techie\" | 25 March 2021",
"notable": false,
"startDate": "2021-03-25T00:00:00.000Z"
},
"malware": [
{
"id": "4b50dfbdfb-901a-1cb4cf8a21fb",
"name": "AgentTesla"
}
],
"techniques": [
{
"id": "e488ddfbdfb20-a1aa-d1a85494067c",
"name": "Compressed Executable"
}
]
}
}
}
Human Readable Output
Campaign Information
Id Name Description Start Date Notable f3ff08dfbdb5e-b3fe-d05f97b2ed3f AgentTesla | Compressed Executables | “techie” | 25 March 2021 Messages purporting to be e.g.
* from <xxxx@xxx.com>’ and subject “Re: New Order From customer”.
These messages contain compressed executables that lead to the installation of AgentTesla with the following example configuration:
<pre>C2_Email_Address: xxxx@xxx.com
C2_Email_Password:
C2_Email_Server: xxxx@xxx.com</pre>2021-03-25T00:00:00.000Z false Campaign Members
No entries.
Families
Id Name 69a63403-dbfdfb4cb-3d2ffb85b98e Keylogger Techniques
Id Name e48835be-xcvxcvaa-d1a85494067c Compressed Executable Actors
No entries.
Brands
No entries.
Malware
Id Name 4b500558-23d0-sfdsdf1cb4cf8a21fb AgentTesla
proofpoint-list-most-attacked-users
Gets a list of the most attacked users in the organization.
Base Command
proofpoint-list-most-attacked-users
Input
| Argument Name | Description | Required |
|---|---|---|
| window | An integer indicating how many days the data should be retrieved for. Possible values: “14”, “30”, “90”. Possible values are: 14, 30, 90. Default is false. | Required |
| limit | The maximum number of users to produce in the response. Default is 1000. | Optional |
| page | The page of results to return. Default is 1. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.Vap.users | List | List of users in the organization. |
| Proofpoint.Vap.totalVapUsers | Number | The total number of VAP users for the interval. |
| Proofpoint.Vap.interval | String | An ISO8601-formatted interval showing the time the response was calculated for. |
| Proofpoint.Vap.averageAttackIndex | Number | The average attack index value for users during the interval. |
| Proofpoint.Vap.vapAttackIndexThreshold | Number | This interval’s attack index threshold, past which a user is considered a VAP. |
Command Example
!proofpoint-list-most-attacked-users window="14"
Context Example
{
"Proofpoint": {
"Vap": {
"averageAttackIndex": 307.05145,
"interval": "2021-05-23T21:44:53Z/2021-06-06T21:44:53Z",
"totalVapUsers": 1,
"users": [
{
"identity": {
"customerUserId": null,
"department": null,
"emails": [
"xxxx@xxx.com"
],
"guid": "3b5132sdvsd76-c442-919e69175bdd",
"location": null,
"name": null,
"title": null,
"vip": false
},
"threatStatistics": {
"attackIndex": 4576,
"families": [
{
"name": "credential phishing",
"score": 7008
}
]
}
}
],
"vapAttackIndexThreshold": 965.9637
}
}
}
Human Readable Output
Most Attacked Users Information
Total Vap Users Interval Average Attack Index Vap Attack Index Threshold 7 2021-05-23T21:44:53Z/2021-06-06T21:44:53Z 307.05145 965.9637 Threat Families
Mailbox Threat Family Name Threat Score xxxx@xxx.com credential phishing 7008
proofpoint-get-top-clickers
Gets a list of the top clickers in the organization for a specified time period.
Base Command
proofpoint-get-top-clickers
Input
| Argument Name | Description | Required |
|---|---|---|
| window | An integer indicating how many days the data should be retrieved for. Possible values: “14”, “30”, “90”. Possible values are: 14, 30, 90. Default is false. | Required |
| limit | The maximum number of top clickers to produce in the response.The max supported value is 200. Default is 100. | Optional |
| page | The page of results to return. Default is 1. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.Topclickers.users | List | List of users in the organization. |
| Proofpoint.Topclickers.totalTopClickers | int | The total number of top clickers in the time interval. |
| Proofpoint.Topclickers.interval | Date | An ISO8601-formatted interval showing the time the response was calculated for. |
Command Example
!proofpoint-get-top-clickers window="90"
Context Example
{
"Proofpoint": {
"Topclickers": {
"interval": "2021-03-09T07:17:00Z/2021-06-07T07:17:00Z",
"totalTopClickers": 1,
"users": [
{
"clickStatistics": {
"clickCount": 2,
"families": [
{
"clicks": 2,
"name": "Malware"
}
]
},
"identity": {
"customerUserId": null,
"department": null,
"emails": [
"xxxx@xxx.come"
],
"guid": "44fa5svfdgae-f22f-b49b49b1e4e3",
"location": null,
"name": null,
"title": null,
"vip": false
}
}
]
}
}
}
Human Readable Output
Top Clickers Users Information
Total Top Clickers Interval 1 2021-03-09T07:17:00Z/2021-06-07T07:17:00Z Threat Families
Mailbox Threat Family Name Threat Score xxxx@xxx.com Malware
proofpoint-url-decode
Decodes URLs that have been rewritten by TAP to their original, target URL.
Base Command
proofpoint-url-decode
Input
| Argument Name | Description | Required |
|---|---|---|
| urls | A comma-separated list of encoded URLs. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.URL.encodedUrl | String | The original, rewritten URL supplied to the endpoint. |
| Proofpoint.URL.decodedUrl | String | The target URL embedded inside the rewritten link. |
| Proofpoint.URL.success | Boolean | Indicates whether the URL could successfully be decoded. |
Command Example
!proofpoint-url-decode urls="https://urldefense.proofpoint.com/v2/url?u=http-3A__links.mkt3337.com_ctt-3Fkn-3D3-26ms-3DMzQ3OTg3MDQS1-26r-3DMzkxNzk3NDkwMDA0S0-26b-3D0-26j-3DMTMwMjA1ODYzNQS2-26mt-3D1-26rt-3D0&d=DwMFaQ&c=Vxt5e0Osvvt2gflwSlsJ5DmPGcPvTRKLJyp031rXjhg&r=MujLDFBJstxoxZI_GKbsW7wxGM7nnIK__qZvVy6j9Wc&m=QJGhloAyfD0UZ6n8r6y9dF-khNKqvRAIWDRU_K65xPI&s=ew-rOtBFjiX1Hgv71XQJ5BEgl9TPaoWRm_Xp9Nuo8bk&e="
Context Example
{
"Proofpoint": {
"URL": {
"decodedUrl": "http://links.mkt3337.com/ctt?kn=3&ms=MzQ3OTg3MDQS1&r=MzkxNzk3NDkwMDA0S0&b=0&j=MTMwMjA1ODYzNQS2&mt=1&rt=0",
"encodedUrl": "https://urldefense.proofpoint.com/v2/url?u=http-3A__links.mkt3337.com_ctt-3Fkn-3D3-26ms-3DMzQ3OTg3MDQS1-26r-3DMzkxNzk3NDkwMDA0S0-26b-3D0-26j-3DMTMwMjA1ODYzNQS2-26mt-3D1-26rt-3D0&d=DwMFaQ&c=Vxt5e0Osvvt2gflwSlsJ5DmPGcPvTRKLJyp031rXjhg&r=MujLDFBJstxoxZI_GKbsW7wxGM7nnIK__qZvVy6j9Wc&m=QJGhloAyfD0UZ6n8r6y9dF-khNKqvRAIWDRU_K65xPI&s=ew-rOtBFjiX1Hgv71XQJ5BEgl9TPaoWRm_Xp9Nuo8bk&e=",
"success": true
}
}
}
Human Readable Output
URLs decoded information
Encoded Url Decoded Url https://urldefense.proofpoint.com/v2/url?u=http-3A__links.mkt3337.com_ctt-3Fkn-3D3-26ms-3DMzQ3OTg3MDQS1-26r-3DMzkxNzk3NDkwMDA0S0-26b-3D0-26j-3DMTMwMjA1ODYzNQS2-26mt-3D1-26rt-3D0&d=DwMFaQ&c=Vxt5e0Osvvt2gflwSlsJ5DmPGcPvTRKLJyp031rXjhg&r=MujLDFBJstxoxZI_GKbsW7wxGM7nnIK__qZvVy6j9Wc&m=QJGhloAyfD0UZ6n8r6y9dF-khNKqvRAIWDRU_K65xPI&s=ew-rOtBFjiX1Hgv71XQJ5BEgl9TPaoWRm_Xp9Nuo8bk&e= http://links.mkt3337.com/ctt?kn=3&ms=MzQ3OTg3MDQS1&r=MzkxNzk3NDkwMDA0S0&b=0&j=MTMwMjA1ODYzNQS2&mt=1&rt=0
Configuration parameters
url— Server URL (required)credentials— Service Principal (required)api_version— API Versioninsecure— Trust any certificate (not secure)proxy— Use system proxy settingsthreat_type— Threat typethreat_status— Threat statusevents_type— Events to fetchlimit— Maximum number of incident per fetchfetch_time— First fetch time rangeraw_json_encoding— Advanced: Raw message encodinglook_back_minutes— Events Fetch Look-Back (minutes)isFetch— Fetch incidentsincidentType— Incident typeincidentFetchInterval— Incidents Fetch Interval
Commands (12)
-
proofpoint-get-campaignGets details for a given campaign.
-
proofpoint-get-eventsFetches events for all clicks and messages relating to known threats within the specified time period. Details as per clicks/blocked.
-
proofpoint-get-events-clicks-blockedGets events for clicks to malicious URLs blocked in the specified time period. Must provide either the interval or time_range arguments.
-
proofpoint-get-events-clicks-permittedGet events for clicks to malicious URLs permitted in the specified time period. Must provide either the interval or time_range arguments.
-
proofpoint-get-events-messages-blockedGet events for blocked messages in the specified time period. Must provide either the interval or time_range arguments.
-
proofpoint-get-events-messages-deliveredGet events for delivered messages in the specified time period. Must provide either the interval or time_range arguments.
-
proofpoint-get-forensicsReturns forensics evidence.
-
proofpoint-get-top-clickersGets a list of the top clickers in the organization for a specified time period.
-
proofpoint-list-campaignsGets a list of IDs of campaigns active in a specified time period. Must provide either the interval or time_range arguments.
-
proofpoint-list-issuesGet events for clicks to malicious URLs permitted and messages delivered containing a known attachment threat within the specified time period. Must provide either the interval or time_range arguments.
-
proofpoint-list-most-attacked-usersGets a list of the most attacked users in the organization.
-
proofpoint-url-decodeDecodes URLs that have been rewritten by TAP to their original, target URL.
import json from datetime import datetime import pytest from freezegun import freeze_time from ProofpointTAP_v2 import ALL_EVENTS, ISSUES_EVENTS, Client, fetch_incidents, get_events_command DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ" MOCK_URL = "http://123-fake-api.com" MOCK_DELIVERED_MESSAGE = { "GUID": "1111", "QID": "r2FNwRHF004109", "ccAddresses": ["bruce.wayne@university-of-education.zz"], "clusterId": "pharmtech_hosted", "fromAddress": "badguy@evil.zz", "headerCC": '"Bruce Wayne" <bruce.wayne@university-of-education.zz>', "headerFrom": '"A. Badguy" <badguy@evil.zz>', "headerReplyTo": None, "headerTo": '"Clark Kent" <clark.kent@pharmtech.zz>; "Diana Prince" <diana.prince@pharmtech.zz>', "impostorScore": 0, "malwareScore": 100, "messageID": "1111@evil.zz", "threatsInfoMap": [ { "campaignId": "46e01b8a-c899-404d-bcd9-189bb393d1a7", "classification": "MALWARE", "threat": "threat_num", "threatId": "threat_num", "threatStatus": "active", "threatTime": "2010-01-30T00:00:40.000Z", "threatType": "ATTACHMENT", "threatUrl": "https://threatinsight.proofpoint.com/43fc1aa4c1cd0146d334c5593b1428f6d062b2c406e5efe8abe95ca", }, { "campaignId": "46e01b8a-c899-404d-bcd9-189bb393d1a7", "classification": "MALWARE", "threat": "badsite.zz", "threatId": "3ba97fc852c66a7ba761450edfdfb9f4ffab74715b591294f78b5e37a76481aa", "threatTime": "2010-01-30T00:00:30.000Z", "threatType": "URL", "threatUrl": "https://threatinsight.proofpoint.com/a7ba761450edfdfb9f4ffab74715b591294f78b5e37a76481aa", }, ], "messageTime": "2010-01-30T00:00:59.000Z", "modulesRun": ["pdr", "sandbox", "spam", "urldefense"], "phishScore": 46, "policyRoutes": ["default_inbound", "executives"], "quarantineFolder": "Attachment Defense", "quarantineRule": "module.sandbox.threat", "recipient": ["clark.kent@pharmtech.zz", "diana.prince@pharmtech.zz"], "replyToAddress": None, "sender": "e99d7ed5580193f36a51f597bc2c0210@evil.zz", "senderIP": "192.0.2.255", "spamScore": 4, "subject": "Please find a totally safe invoice attached.", "toAddresses": "xx@xxx.com", "xmailer": None, } MOCK_BLOCKED_MESSAGE = { "GUID": "2222", "QID": "r2FNwRHF004109", "ccAddresses": ["bruce.wayne@university-of-education.zz"], "clusterId": "pharmtech_hosted", "fromAddress": "badguy@evil.zz", "headerCC": '"Bruce Wayne" <bruce.wayne@university-of-education.zz>', "headerFrom": '"A. Badguy" <badguy@evil.zz>', "headerReplyTo": None, "headerTo": '"Clark Kent" <clark.kent@pharmtech.zz>; "Diana Prince" <diana.prince@pharmtech.zz>', "impostorScore": 0, "malwareScore": 100, "messageID": "2222@evil.zz", "threatsInfoMap": [ { "campaignId": "46e01b8a-c899-404d-bcd9-189bb393d1a7", "classification": "MALWARE", "threat": "threat_num", "threatId": "threat_num", "threatStatus": "active", "threatTime": "2010-01-25T00:00:40.000Z", "threatType": "ATTACHMENT", "threatUrl": "https://threatinsight.proofpoint.com/43fc1aa4c1cd0146d334c5593b1428f6d062b2c406e5efe8abe95ca", }, { "campaignId": "46e01b8a-c899-404d-bcd9-189bb393d1a7", "classification": "MALWARE", "threat": "badsite.zz", "threatId": "3ba97fc852c66a7ba761450edfdfb9f4ffab74715b591294f78b5e37a76481aa", "threatTime": "2010-01-25T00:00:30.000Z", "threatType": "URL", "threatUrl": "https://threatinsight.proofpoint.com/a7ba761450edfdfb9f4ffab74715b591294f78b5e37a76481aa", }, ], "messageTime": "2010-01-25T00:00:10.000Z", "modulesRun": ["pdr", "sandbox", "spam", "urldefense"], "phishScore": 46, "policyRoutes": ["default_inbound", "executives"], "quarantineFolder": "Attachment Defense", "quarantineRule": "module.sandbox.threat", "recipient": ["clark.kent@pharmtech.zz", "diana.prince@pharmtech.zz"], "replyToAddress": None, "sender": "e99d7ed5580193f36a51f597bc2c0210@evil.zz", "senderIP": "192.0.2.255", "spamScore": 4, "subject": "Please find a totally safe invoice attached.", "toAddresses": "xx@xxx.com", "xmailer": None, } MOCK_PERMITTED_CLICK = { "id": "click-permitted-1", "campaignId": "46e01b8a-c899-404d-bcd9-189bb393d1a7", "classification": "MALWARE", "clickIP": "192.0.2.1", "clickTime": "2010-01-11T00:00:20.000Z", "messageID": "3333", "recipient": "bruce.wayne@pharmtech.zz", "sender": "9facbf452def2d7efc5b5c48cdb837fa@badguy.zz", "senderIP": "192.0.2.255", "threatID": "threat_num2", "threatTime": "2010-01-11T00:00:10.000Z", "threatURL": "https://threatinsight.proofpoint.com/#/f7622167144dba5e3ae4480eeee78b23d66f7dfed970cfc3d086cc0dabdf50", "url": "http://badguy.zz/", "userAgent": "Mozilla/5.0(WindowsNT6.1;WOW64;rv:27.0)Gecko/20100101Firefox/27.0", } MOCK_BLOCKED_CLICK = { "id": "click-blocked-1", "campaignId": "46e01b8a-c899-404d-bcd9-189bb393d1a7", "classification": "MALWARE", "clickIP": "192.0.2.2", "clickTime": "2010-01-22T00:00:10.000Z", "messageID": "4444", "recipient": "bruce.wayne@pharmtech.zz", "sender": "9facbf452def2d7efc5b5c48cdb837fa@badguy.zz", "senderIP": "192.0.2.255", "threatID": "threat_num2", "threatTime": "2010-01-22T00:00:20.000Z", "threatURL": "https://threatinsight.proofpoint.com/#/f7622167144dba5e3ae4480eeee78b23d66f7dfed970cfc3d086cc0dabdf50", "url": "http://badguy.zz/", "userAgent": "Mozilla/5.0(WindowsNT6.1;WOW64;rv:27.0)Gecko/20100101Firefox/27.0", } MOCK_ISSUES = {"messagesDelivered": [MOCK_DELIVERED_MESSAGE], "clicksPermitted": [MOCK_PERMITTED_CLICK]} MOCK_ALL_EVENTS = { "messagesDelivered": [MOCK_DELIVERED_MESSAGE], "clicksPermitted": [MOCK_PERMITTED_CLICK], "clicksBlocked": [MOCK_BLOCKED_CLICK], "messagesBlocked": [MOCK_BLOCKED_MESSAGE], } # Additional "new event" mocks for the look-back + dedup tests. # These are derived from the existing mocks above by copying them and overriding # only the dedup-key field (GUID for messages, id for clicks). They represent # genuinely new events that should NOT collide with the previously-seen IDs. MOCK_NEW_DELIVERED_MESSAGE = {**MOCK_DELIVERED_MESSAGE, "GUID": "9999", "messageID": "9999@evil.zz"} MOCK_NEW_BLOCKED_CLICK = {**MOCK_BLOCKED_CLICK, "id": "click-blocked-NEW"} def get_mocked_time(): return datetime.strptime("2010-01-01T00:00:00Z", "%Y-%m-%dT%H:%M:%SZ") def test_command(requests_mock): requests_mock.get( MOCK_URL + "/v2/siem/issues?format=json&sinceSeconds=100&threatType=url&threatType=attachment", json=MOCK_ISSUES ) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) args = {"threatType": "url,attachment", "sinceSeconds": "100", "eventTypes": ISSUES_EVENTS} _, outputs, _ = get_events_command(client, args) assert len(outputs["Proofpoint.MessagesDelivered(val.GUID == obj.GUID)"]) == 1 assert len(outputs["Proofpoint.ClicksPermitted(val.GUID == obj.GUID)"]) == 1 def return_self(return_date): return return_date @freeze_time("2010-01-01T00:00:00Z", tz_offset=0) def test_first_fetch_incidents(requests_mock, mocker): requests_mock.get( MOCK_URL + "/v2/siem/all?format=json&interval=2009-12-31T23%3A30%3A00Z%2F2010-01-01T00%3A00%3A00Z", json=MOCK_ALL_EVENTS ) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) next_run, incidents, _ = fetch_incidents( client=client, last_run={}, first_fetch_time="30 minutes", event_type_filter=ALL_EVENTS, threat_status="", threat_type="" ) assert len(incidents) == 4 assert json.loads(incidents[3]["rawJSON"])["messageID"] == "4444" def test_next_fetch(requests_mock, mocker): # Use 31 minutes to ensure interval is >= 30 seconds current_date = "2010-01-01T00:31:00Z" mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime(current_date, "%Y-%m-%dT%H:%M:%SZ")) requests_mock.get( MOCK_URL + "/v2/siem/all?format=json&interval=2010-01-01T00%3A00%3A00Z%" "2F2010-01-01T00%3A31%3A00Z&threatStatus=active&threatStatus=cleared", json=MOCK_ALL_EVENTS, ) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) next_run, incidents, _ = fetch_incidents( client=client, last_run={"last_fetch": "2010-01-01T00:00:00Z"}, first_fetch_time="3 days", event_type_filter=ALL_EVENTS, threat_status=["active", "cleared"], threat_type="", limit=50, look_back_minutes=0, ) assert len(incidents) == 4 assert json.loads(incidents[3]["rawJSON"])["messageID"] == "4444" def test_fetch_limit(requests_mock, mocker): # Use 31 minutes to ensure interval is >= 30 seconds current_date = "2010-01-01T00:31:00Z" this_run = {"last_fetch": "2010-01-01T00:00:00Z"} mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime(current_date, "%Y-%m-%dT%H:%M:%SZ")) requests_mock.get(MOCK_URL + "/v2/siem/all", json=MOCK_ALL_EVENTS) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) next_run, incidents, remained = fetch_incidents( client=client, last_run=this_run, first_fetch_time="3 days", event_type_filter=ALL_EVENTS, threat_status=["active", "cleared"], threat_type="", limit=3, look_back_minutes=0, ) assert next_run["last_fetch"] == "2010-01-01T00:31:00Z" assert len(incidents) == 3 assert len(remained) == 1 # test another run next_run, incidents, remained = fetch_incidents( client=client, last_run=this_run, first_fetch_time="3 days", event_type_filter=ALL_EVENTS, threat_status=["active", "cleared"], threat_type="", limit=3, integration_context={"incidents": remained}, look_back_minutes=0, ) assert next_run["last_fetch"] == "2010-01-01T00:00:00Z" assert len(incidents) == 1 assert not remained @freeze_time("2010-01-01T00:01:00Z", tz_offset=0) def test_fetch_incidents_with_encoding(requests_mock, mocker): """ Given: - Message with latin chars in its subject - Raw JSON encoding param set to latin-1 When: - Running fetch incidents Then: - Ensure subject is returned properly in the raw JSON """ # Mock time to be 1 minute after the parsed time to ensure >= 30 second interval mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime("2010-01-01T00:01:00Z", "%Y-%m-%dT%H:%M:%SZ")) mocker.patch("ProofpointTAP_v2.parse_date_range", return_value=("2010-01-01T00:00:00Z", "never mind")) requests_mock.get( MOCK_URL + "/v2/siem/all?format=json&interval=2010-01-01T00%3A00%3A00Z%2F2010-01-01T00%3A01%3A00Z", json={ "messagesDelivered": [ { "subject": "p\u00c3\u00a9rdida", "messageTime": "2010-01-30T00:00:59.000Z", }, ], }, ) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None, ) _, incidents, _ = fetch_incidents( client=client, last_run={}, first_fetch_time="now", event_type_filter=ALL_EVENTS, threat_status="", threat_type="", raw_json_encoding="latin-1", look_back_minutes=0, ) assert json.loads(incidents[0]["rawJSON"])["subject"] == "pérdida" # Test data: (last_fetch, current_time, expected_interval_count) # Old format returned list of timestamps, new format returns list of (start, end) tuples FETCH_TIMES_MOCK = [ ("2010-01-01T00:00:00Z", "2010-01-01T03:00:00Z", 4), # 3 hours = 3 intervals of 59min + 1 final interval ("2010-01-01T00:00:00Z", "2010-01-01T00:03:00Z", 1), # 3 minutes = 1 interval ] @pytest.mark.parametrize("mock_past, mock_now, expected", FETCH_TIMES_MOCK) def test_get_fetch_times(mocker, mock_past, mock_now, expected): from ProofpointTAP_v2 import get_fetch_times mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime(mock_now, "%Y-%m-%dT%H:%M:%SZ")) intervals = get_fetch_times(mock_past) assert len(intervals) == expected # Verify all intervals are tuples of (start, end) for interval in intervals: assert isinstance(interval, tuple) assert len(interval) == 2 start, end = interval assert isinstance(start, str) assert isinstance(end, str) # Test data for the conditional look-back logic of get_fetch_times. # Each row: (last_fetch, now, look_back_minutes, expected_first_interval_start, expected_last_interval_end) # Logic under test: # effective_start = now - max(now - last_fetch, look_back_minutes) # i.e. the window is expanded ONLY when the existing gap is smaller than look_back_minutes. GET_FETCH_TIMES_LOOKBACK_MOCK = [ # 1. look_back_minutes=0 -> behavior unchanged, start == last_fetch. ( "2010-01-01T00:00:00Z", "2010-01-01T00:05:00Z", 0, "2010-01-01T00:00:00Z", "2010-01-01T00:05:00Z", ), # 2. now - last_fetch (1 min) < look_back_minutes (10) -> window expanded to look_back. # effective_start = now - 10min = 2009-12-31T23:51:00Z. ( "2010-01-01T00:00:00Z", "2010-01-01T00:01:00Z", 10, "2009-12-31T23:51:00Z", "2010-01-01T00:01:00Z", ), # 3. now - last_fetch (5 min) >= look_back_minutes (2) -> window unchanged, # look-back is NOT added on top. effective_start stays at last_fetch. ( "2010-01-01T00:00:00Z", "2010-01-01T00:05:00Z", 2, "2010-01-01T00:00:00Z", "2010-01-01T00:05:00Z", ), ] @pytest.mark.parametrize( "last_fetch, mock_now, look_back_minutes, expected_start, expected_end", GET_FETCH_TIMES_LOOKBACK_MOCK, ) def test_get_fetch_times_look_back_conditional(mocker, last_fetch, mock_now, look_back_minutes, expected_start, expected_end): """ Given: - A `last_fetch` timestamp, the current time `now`, and a `look_back_minutes` value. When: - `get_fetch_times` is called. Then: - The effective start is `now - max(now - last_fetch, look_back_minutes)`. * look_back_minutes=0 -> start == last_fetch (no change). * gap < look_back -> start == now - look_back_minutes (window expanded). * gap >= look_back -> start == last_fetch (look-back NOT added on top). - The window ends at `now`. """ from ProofpointTAP_v2 import get_fetch_times mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime(mock_now, "%Y-%m-%dT%H:%M:%SZ")) intervals = get_fetch_times(last_fetch, look_back_minutes=look_back_minutes) assert intervals, "expected at least one interval" assert intervals[0][0] == expected_start assert intervals[-1][1] == expected_end def test_fetch_with_look_back_buffer(requests_mock, mocker): """ Scenario: Fetch incidents with look-back buffer to account for Proofpoint API indexing delay. Given: - User has configured look_back_minutes=10 to prevent missing events. - Last fetch was at 2010-01-01T00:00:00Z. - Current time is 2010-01-01T00:01:00Z (gap of 1 min < look_back of 10 min). When: - fetch_incidents is called with look_back_minutes=10. Then: - Ensure the fetch window is expanded so its length equals look_back_minutes: effective_start = now - 10min = 2009-12-31T23:51:00Z. - Ensure the fetch end is current time 2010-01-01T00:01:00Z. - Ensure incidents are fetched correctly. - Ensure next_run checkpoint is set to the end of the last interval (now). """ from ProofpointTAP_v2 import fetch_incidents last_fetch_time = "2010-01-01T00:00:00Z" current_time = "2010-01-01T00:01:00Z" # gap (1 min) < look_back (10 min) -> effective_start = now - 10min = 23:51:00 previous day expected_start_time = "2009-12-31T23:51:00Z" # End time is now expected_end_time = current_time mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime(current_time, "%Y-%m-%dT%H:%M:%SZ")) # Mock API call with the expected look-back interval (single interval since < 59 minutes) start_encoded = expected_start_time.replace(":", "%3A") end_encoded = expected_end_time.replace(":", "%3A") requests_mock.get( MOCK_URL + f"/v2/siem/all?format=json&interval={start_encoded}%2F{end_encoded}", json=MOCK_ALL_EVENTS, ) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) next_run, incidents, _ = fetch_incidents( client=client, # Include an empty `seen_ids` to mark this instance as already initialized # for look-back/dedup tracking (NOT a legacy upgrade), so the look-back is # applied immediately at its configured value. last_run={"last_fetch": last_fetch_time, "seen_ids": {}}, first_fetch_time="3 days", event_type_filter=ALL_EVENTS, threat_status="", threat_type="", limit=50, look_back_minutes=10, ) # Verify incidents were fetched assert len(incidents) == 4 # Verify checkpoint is set to the end of the last interval (current time) assert next_run["last_fetch"] == expected_end_time # --------------------------------------------------------------------------- # Look-back + Deduplication tests # --------------------------------------------------------------------------- # The integration tracks already-seen events in `last_run["seen_ids"]` as a # dict {dedup_key: interval_end_str}. Dedup keys per event type: # - messagesDelivered -> "GUID" # - messagesBlocked -> "GUID" # - clicksPermitted -> "id" # - clicksBlocked -> "id" # --------------------------------------------------------------------------- def test_dedup_filters_already_seen_incidents_in_lookback_window(requests_mock, mocker): """ Given: - last_run.seen_ids contains all four event IDs from a previous fetch, and look_back_minutes=2 so the previous window is rescanned. - The API returns the exact same events again because of the overlap. When: - fetch_incidents is called. Then: - All already-seen events are filtered; zero incidents are produced. - The seen_ids dedup state is preserved (not lost) in next_run. - last_fetch advances to the end of the last fetched interval. """ last_fetch_time = "2010-01-01T00:00:00Z" current_time = "2010-01-01T00:01:00Z" interval_end_seen = "2010-01-01T00:00:00Z" mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime(current_time, "%Y-%m-%dT%H:%M:%SZ")) # API returns the same events that were already fetched previously. requests_mock.get(MOCK_URL + "/v2/siem/all", json=MOCK_ALL_EVENTS) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) # Previously-seen IDs (mapped to the interval end in which they were first seen, # which must be within the lookback window so they are not pruned). seen_ids = { MOCK_DELIVERED_MESSAGE["GUID"]: interval_end_seen, MOCK_BLOCKED_MESSAGE["GUID"]: interval_end_seen, MOCK_PERMITTED_CLICK["id"]: interval_end_seen, MOCK_BLOCKED_CLICK["id"]: interval_end_seen, } next_run, incidents, remained = fetch_incidents( client=client, last_run={"last_fetch": last_fetch_time, "seen_ids": dict(seen_ids)}, first_fetch_time="3 days", event_type_filter=ALL_EVENTS, threat_status="", threat_type="", limit=50, look_back_minutes=2, ) # All four events were already seen -> filtered out assert incidents == [] assert remained == [] # Dedup state is retained in next_run (not lost) — all 4 previously-seen IDs still present assert set(next_run["seen_ids"].keys()) == set(seen_ids.keys()) # last_fetch advances to the end of the last fetched interval (= current time) assert next_run["last_fetch"] == current_time def test_dedup_includes_new_events_within_lookback_window(requests_mock, mocker): """ Given: - last_run.seen_ids contains IDs of a delivered message and a blocked click from a previous fetch. - The API returns a mix of those previously-seen events AND new events (MOCK_NEW_DELIVERED_MESSAGE, MOCK_NEW_BLOCKED_CLICK) within the overlapped lookback window. - look_back_minutes=2. When: - fetch_incidents is called. Then: - Only the new (unseen) events become incidents. - next_run.seen_ids contains both the previously-seen IDs (still in window) AND the new IDs from this fetch. """ last_fetch_time = "2010-01-01T00:00:00Z" current_time = "2010-01-01T00:05:00Z" interval_end_seen = "2010-01-01T00:00:00Z" mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime(current_time, "%Y-%m-%dT%H:%M:%SZ")) api_response = { "messagesDelivered": [MOCK_DELIVERED_MESSAGE, MOCK_NEW_DELIVERED_MESSAGE], "messagesBlocked": [], "clicksPermitted": [], "clicksBlocked": [MOCK_BLOCKED_CLICK, MOCK_NEW_BLOCKED_CLICK], } requests_mock.get(MOCK_URL + "/v2/siem/all", json=api_response) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) previously_seen = { MOCK_DELIVERED_MESSAGE["GUID"]: interval_end_seen, MOCK_BLOCKED_CLICK["id"]: interval_end_seen, } next_run, incidents, _ = fetch_incidents( client=client, last_run={"last_fetch": last_fetch_time, "seen_ids": dict(previously_seen)}, first_fetch_time="3 days", event_type_filter=ALL_EVENTS, threat_status="", threat_type="", limit=50, look_back_minutes=2, ) # Only the two new events become incidents assert len(incidents) == 2 raw_jsons = [json.loads(inc["rawJSON"]) for inc in incidents] fetched_dedup_keys = {raw.get("GUID") or raw.get("id") for raw in raw_jsons} assert fetched_dedup_keys == {MOCK_NEW_DELIVERED_MESSAGE["GUID"], MOCK_NEW_BLOCKED_CLICK["id"]} # next_run.seen_ids contains BOTH old (still within window) and new IDs final_ids = set(next_run["seen_ids"].keys()) assert MOCK_DELIVERED_MESSAGE["GUID"] in final_ids # old, retained assert MOCK_BLOCKED_CLICK["id"] in final_ids # old, retained assert MOCK_NEW_DELIVERED_MESSAGE["GUID"] in final_ids # new assert MOCK_NEW_BLOCKED_CLICK["id"] in final_ids # new def test_lookback_zero_prunes_stale_ids(requests_mock, mocker): """ Given: - look_back_minutes=0 (default behavior, no lookback). - last_run carries a stale seen_ids entry that does not collide with the new events from the API. - The API returns brand-new events in a non-overlapping window. When: - fetch_incidents is called. Then: - All events from the API window become incidents (no dedup-driven drops). - The seen_ids in next_run is pruned (pruning runs unconditionally to prevent unbounded last_run growth) — the ancient stale ID is removed while the freshly-tracked new IDs remain. """ last_fetch_time = "2010-01-01T00:00:00Z" current_time = "2010-01-01T00:31:00Z" mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime(current_time, "%Y-%m-%dT%H:%M:%SZ")) requests_mock.get(MOCK_URL + "/v2/siem/all", json=MOCK_ALL_EVENTS) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) # A stale dedup ID that is far older than any look-back window. pre_existing_seen = {"ancient-id": "2000-01-01T00:00:00Z"} next_run, incidents, _ = fetch_incidents( client=client, last_run={"last_fetch": last_fetch_time, "seen_ids": dict(pre_existing_seen)}, first_fetch_time="3 days", event_type_filter=ALL_EVENTS, threat_status="", threat_type="", limit=50, look_back_minutes=0, ) # All 4 events appear: no dedup overlap because the pre-existing seen ID # doesn't collide with the new event dedup keys. assert len(incidents) == 4 # With look_back_minutes=0 pruning still runs (cutoff = now - 30min), so the # ancient stale ID is dropped, but the freshly-tracked new IDs (interval_end # = current_time) are preserved. final_ids = set(next_run["seen_ids"].keys()) assert "ancient-id" not in final_ids assert MOCK_DELIVERED_MESSAGE["GUID"] in final_ids assert MOCK_BLOCKED_MESSAGE["GUID"] in final_ids assert MOCK_PERMITTED_CLICK["id"] in final_ids assert MOCK_BLOCKED_CLICK["id"] in final_ids def test_lookback_dedup_state_pruning(requests_mock, mocker): """ Given: - last_run.seen_ids contains a mix of IDs: * one mapped to an interval_end well outside the lookback window (must be pruned), * one mapped to an interval_end inside the lookback window (must be kept). - look_back_minutes=5 -> prune cutoff = now - (5 + 30) min. When: - fetch_incidents is called. Then: - The stale ID is removed from next_run.seen_ids. - The in-window ID is preserved. """ last_fetch_time = "2010-01-01T00:55:00Z" current_time = "2010-01-01T01:00:00Z" mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime(current_time, "%Y-%m-%dT%H:%M:%SZ")) # Empty API response so we focus purely on pruning behavior. requests_mock.get( MOCK_URL + "/v2/siem/all", json={"messagesDelivered": [], "messagesBlocked": [], "clicksPermitted": [], "clicksBlocked": []}, ) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) # Cutoff for look_back_minutes=5 is now - 35min = 2010-01-01T00:25:00Z. seen_ids = { "stale-id": "2009-12-31T00:00:00Z", # way before cutoff -> pruned "fresh-id": "2010-01-01T00:55:00Z", # after cutoff -> kept } next_run, incidents, _ = fetch_incidents( client=client, last_run={"last_fetch": last_fetch_time, "seen_ids": dict(seen_ids)}, first_fetch_time="3 days", event_type_filter=ALL_EVENTS, threat_status="", threat_type="", limit=50, look_back_minutes=5, ) assert incidents == [] assert "stale-id" not in next_run["seen_ids"] assert "fresh-id" in next_run["seen_ids"] def test_lookback_first_fetch_initializes_dedup_state(requests_mock, mocker): """ Given: - First fetch (last_run = {}) with look_back_minutes=2. - The API returns the standard set of all four events. When: - fetch_incidents is called. Then: - The seen_ids dedup state is initialized in next_run with the dedup keys of every fetched incident (GUIDs for messages, ids for clicks). - All events become incidents and last_fetch is populated. """ current_time = "2010-01-01T00:05:00Z" mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime(current_time, "%Y-%m-%dT%H:%M:%SZ")) # parse_date_range returns the first_fetch start time for a clean first-fetch flow. mocker.patch("ProofpointTAP_v2.parse_date_range", return_value=("2010-01-01T00:00:00Z", "never mind")) requests_mock.get(MOCK_URL + "/v2/siem/all", json=MOCK_ALL_EVENTS) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) next_run, incidents, _ = fetch_incidents( client=client, last_run={}, # first fetch first_fetch_time="30 minutes", event_type_filter=ALL_EVENTS, threat_status="", threat_type="", limit=50, look_back_minutes=2, ) # All 4 events become incidents on first fetch assert len(incidents) == 4 # seen_ids is initialized and contains all 4 dedup keys assert "seen_ids" in next_run expected_ids = { MOCK_DELIVERED_MESSAGE["GUID"], MOCK_BLOCKED_MESSAGE["GUID"], MOCK_PERMITTED_CLICK["id"], MOCK_BLOCKED_CLICK["id"], } assert set(next_run["seen_ids"].keys()) == expected_ids # last_fetch checkpoint is populated (end of last interval = current time) assert next_run["last_fetch"] == current_time class TestGetForensics: PLATFORMS_OBJECT = [ { "name": "windows 7 sp1", "os": "windows 7", "version": "4.5.661", } ] EVIDENCE_OBJECT_URL = { "type": "url", "display": "string", "time": "string", "malicious": "string", "what": { "url": "string", "blacklisted": "boolean", "ip": "string", "httpStatus": "string", "md5": "string", "offset": "integer", "rule": "string", "sha256": "string", "size": "integer", }, "platforms": PLATFORMS_OBJECT, } EVIDENCE_OBJECT_REGISTRY = { "type": "registry", "display": "string", "time": "string", "malicious": "string", "what": { "action": "string", "key": "string", "name": "string", "rule": "string", "value": "string", }, "platforms": PLATFORMS_OBJECT, } EVIDENCE_OBJECT_PROCESS = { "type": "process", "display": "string", "time": "string", "malicious": "string", "what": { "action": "string", "path": "string", }, "platforms": PLATFORMS_OBJECT, } EVIDENCE_OBJECT_NETWORK = { "type": "network", "display": "string", "time": "string", "malicious": "string", "what": { "action": "string", "ip": "string", "port": "string", "type": "string", }, "platforms": PLATFORMS_OBJECT, } EVIDENCE_OBJECT_MUTEX = { "type": "mutex", "display": "string", "time": "string", "malicious": "string", "what": { "name": "string", "path": "string", }, "platforms": PLATFORMS_OBJECT, } EVIDENCE_OBJECT_IDS = { "type": "ids", "display": "string", "time": "string", "malicious": "string", "what": { "name": "string", "signatureId": "integer", }, "platforms": PLATFORMS_OBJECT, } EVIDENCE_OBJECT_FILE = { "type": "file", "display": "string", "time": "string", "malicious": "string", "what": {"action": "string", "md5": "string", "path": "string", "rule": "string", "sha256": "string", "size": "integer"}, "platforms": PLATFORMS_OBJECT, } EVIDENCE_OBJECT_DROPPER = { "type": "dropper", "display": "string", "time": "string", "malicious": "string", "what": {"path": "string", "rule": "string", "url": "string"}, "platforms": PLATFORMS_OBJECT, } EVIDENCE_OBJECT_DNS = { "type": "dns", "display": "string", "time": "string", "malicious": "string", "what": { "host": "string", "cnames": ["string1", "string2"], "ips": ["string1", "string2"], "nameservers": ["string1", "string2"], "nameserversList": ["string1", "string2"], }, "platforms": PLATFORMS_OBJECT, } EVIDENCE_OBJECT_COOKIE = { "type": "cookie", "display": "string", "time": "string", "malicious": "string", "what": {"action": "string", "domain": "string", "key": "string", "value": "string"}, "platforms": PLATFORMS_OBJECT, } EVIDENCE_OBJECT_ATTACHMENT = { "type": "attachment", "display": "string", "time": "string", "malicious": "string", "what": {"sha256": "string", "md5": "string", "offset": "integer", "rule": "string", "size": "integer"}, "platforms": PLATFORMS_OBJECT, } EVIDENCE_LIST = [ EVIDENCE_OBJECT_ATTACHMENT, EVIDENCE_OBJECT_COOKIE, EVIDENCE_OBJECT_DNS, EVIDENCE_OBJECT_DROPPER, EVIDENCE_OBJECT_FILE, EVIDENCE_OBJECT_IDS, EVIDENCE_OBJECT_MUTEX, EVIDENCE_OBJECT_NETWORK, EVIDENCE_OBJECT_PROCESS, EVIDENCE_OBJECT_REGISTRY, EVIDENCE_OBJECT_URL, ] REPORT_OBJECT = [ { "name": "string", "scope": "string", "type": "string", "id": "string", "forensics": EVIDENCE_LIST, } ] REPORT = { "generated": "string", "reports": REPORT_OBJECT * 2, } FORENSICS_REPORT = { "Scope": "string", "Type": "string", "ID": "string", "Attachment": [ { "Time": "string", "Display": "string", "Malicious": "string", "Platform": [{"Name": "windows 7 sp1", "OS": "windows 7", "Version": "4.5.661"}], "SHA256": "string", "MD5": "string", "Offset": "integer", "Size": "integer", } ], "Cookie": [ { "Time": "string", "Display": "string", "Malicious": "string", "Platform": [{"Name": "windows 7 sp1", "OS": "windows 7", "Version": "4.5.661"}], "Action": "string", "Domain": "string", "Key": "string", "Value": "string", } ], "DNS": [ { "Time": "string", "Display": "string", "Malicious": "string", "Platform": [{"Name": "windows 7 sp1", "OS": "windows 7", "Version": "4.5.661"}], "Host": "string", "CNames": ["string1", "string2"], "IP": ["string1", "string2"], "NameServers": ["string1", "string2"], "NameServersList": ["string1", "string2"], } ], "Dropper": [ { "Time": "string", "Display": "string", "Malicious": "string", "Platform": [{"Name": "windows 7 sp1", "OS": "windows 7", "Version": "4.5.661"}], "Path": "string", "URL": "string", "Rule": "string", } ], "File": [ { "Time": "string", "Display": "string", "Malicious": "string", "Platform": [{"Name": "windows 7 sp1", "OS": "windows 7", "Version": "4.5.661"}], "Path": "string", "Action": "string", "SHA256": "string", "MD5": "string", "Size": "integer", } ], "IDS": [ { "Time": "string", "Display": "string", "Malicious": "string", "Platform": [{"Name": "windows 7 sp1", "OS": "windows 7", "Version": "4.5.661"}], "Name": "string", "SignatureID": "integer", } ], "Mutex": [ { "Time": "string", "Display": "string", "Malicious": "string", "Platform": [{"Name": "windows 7 sp1", "OS": "windows 7", "Version": "4.5.661"}], "Name": "string", "Path": "string", } ], "Network": [ { "Time": "string", "Display": "string", "Malicious": "string", "Platform": [{"Name": "windows 7 sp1", "OS": "windows 7", "Version": "4.5.661"}], "Action": "string", "IP": "string", "Port": "string", "Protocol": "string", } ], "Process": [ { "Time": "string", "Display": "string", "Malicious": "string", "Platform": [{"Name": "windows 7 sp1", "OS": "windows 7", "Version": "4.5.661"}], "Action": "string", "Path": "string", } ], "Registry": [ { "Time": "string", "Display": "string", "Malicious": "string", "Platform": [{"Name": "windows 7 sp1", "OS": "windows 7", "Version": "4.5.661"}], "Name": "string", "Action": "string", "Key": "string", "Value": "string", } ], "URL": [ { "Time": "string", "Display": "string", "Malicious": "string", "Platform": [{"Name": "windows 7 sp1", "OS": "windows 7", "Version": "4.5.661"}], "URL": "string", "Blacklisted": "boolean", "SHA256": "string", "MD5": "string", "Size": "integer", "HTTPStatus": "string", "IP": "string", } ], } client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) def test_get_forensics(self, requests_mock): from ProofpointTAP_v2 import get_forensic_command requests_mock.get("http://123-fake-api.com/v2/forensics?threatId=1256", json=self.REPORT) _, output, _ = get_forensic_command(self.client, {"threatId": "1256"}) reports = output["Proofpoint.Report(var.ID === obj.ID)"] assert len(reports) == 2 report = reports[0] assert all(report) assert report == self.FORENSICS_REPORT def load_mock_response(file_name: str) -> str: """ Load mock file that simulates an API response. Args: file_name (str): Name of the mock response JSON file to return. Returns: str: Mock file content. """ with open(f"test_data/{file_name}", encoding="utf-8") as mock_file: return mock_file.read() def test_get_clicks_command(requests_mock): """ Scenario: Retrieves clicks to malicious URLs blocked and permitted in the specified time period. Given: - User has provided valid credentials and arguments. When: - A get-clicks command is called and there is clicks in the response. Then: - Ensure number of items is correct. - Ensure outputs prefix is correct. - Ensure a sample value from the API matches what is generated in the context. """ from ProofpointTAP_v2 import Client, get_clicks_command requests_mock.get( f"{MOCK_URL}/v2/siem/clicks/blocked", json={"queryEndTime": "2021-03-23T14:00:00Z", "clicksBlocked": [MOCK_BLOCKED_CLICK]} ) requests_mock.get( f"{MOCK_URL}/v2/siem/clicks/permitted", json={"queryEndTime": "2021-03-23T14:00:00Z", "clicksPermitted": [MOCK_PERMITTED_CLICK]}, ) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) blocked_result = get_clicks_command(client, True, "3 days") permitted_result = get_clicks_command(client, False, "3 days") assert len(blocked_result.outputs) == 1 assert blocked_result.outputs_prefix == "Proofpoint.ClicksBlocked" assert blocked_result.outputs[0].get("messageID") == "4444" assert len(permitted_result.outputs) == 1 assert permitted_result.outputs_prefix == "Proofpoint.ClicksPermitted" assert permitted_result.outputs[0].get("messageID") == "3333" def test_get_messages_command(requests_mock): """ Scenario: Retrieves messages to malicious URLs blocked and delivered in the specified time period. Given: - User has provided valid credentials and arguments. When: - A get-messages command is called and there is messages in the response. Then: - Ensure number of items is correct. - Ensure outputs prefix is correct. - Ensure a sample value from the API matches what is generated in the context. """ from ProofpointTAP_v2 import Client, get_messages_command requests_mock.get( f"{MOCK_URL}/v2/siem/messages/blocked", json={"queryEndTime": "2021-03-23T14:00:00Z", "messagesBlocked": [MOCK_BLOCKED_MESSAGE]}, ) requests_mock.get( f"{MOCK_URL}/v2/siem/messages/delivered", json={"queryEndTime": "2021-03-23T14:00:00Z", "messagesDelivered": [MOCK_DELIVERED_MESSAGE]}, ) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) blocked_result = get_messages_command(client, True, "3 days") delivered_result = get_messages_command(client, False, "3 days") assert len(blocked_result.outputs) == 1 assert blocked_result.outputs_prefix == "Proofpoint.MessagesBlocked" assert blocked_result.outputs[0].get("messageID") == "2222@evil.zz" assert len(delivered_result.outputs) == 1 assert delivered_result.outputs_prefix == "Proofpoint.MessagesDelivered" assert delivered_result.outputs[0].get("messageID") == "1111@evil.zz" def test_list_campaigns_command(requests_mock): """ Scenario: Retrieves a list of IDs of campaigns active in a time window. Given: - User has provided valid credentials. When: - A list-campaign-ids command is called and there is campaigns in the response. Then: - Ensure number of items is correct. - Ensure outputs prefix is correct. - Ensure a sample value from the API matches what is generated in the context. """ from ProofpointTAP_v2 import Client, list_campaigns_command mock_response = json.loads(load_mock_response("campaigns.json")) requests_mock.get(f"{MOCK_URL}/v2/campaign/ids", json=mock_response) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) result = list_campaigns_command(client, "3 days") assert len(result.outputs) == 2 assert result.outputs_prefix == "Proofpoint.Campaign" assert result.outputs[0].get("id") == "f3ff0874-85ef-475e-b3fe-d05f97b2ed3f" assert result.outputs[0].get("lastUpdatedAt") == "2021-03-25T10:37:46.000Z" def test_get_campaign(requests_mock): """ Scenario: Retrieves information for a given campaign. Given: - User has provided valid credentials and argument. When: - A get-campaign command is called and there is a campaign in the response. Then: - Ensure number of items is correct. - Ensure outputs prefix is correct. - Ensure a sample value from the API matches what is generated in the context. """ from ProofpointTAP_v2 import Client, get_campaign_command mock_response = json.loads(load_mock_response("campaign_information.json")) requests_mock.get(f"{MOCK_URL}/v2/campaign/1", json=mock_response) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) result = get_campaign_command(client, "1") assert len(result.outputs) == 7 assert result.outputs_prefix == "Proofpoint.Campaign" assert result.outputs.get("info").get("id") == "aa9b3d62-4d72-4ebc-8f39-3da3833e7038" def test_list_most_attacked_users_command(requests_mock): """ Scenario: Retrieves a list of the most attacked users in the organization for a given period. Given: - User has provided valid credentials and argument. When: - A get-vap command is called and there is a attacked people in the response. Then: - Ensure number of items is correct. - Ensure outputs prefix is correct. - Ensure a sample value from the API matches what is generated in the context. """ from ProofpointTAP_v2 import Client, list_most_attacked_users_command mock_response = json.loads(load_mock_response("most_attacked_users.json")) requests_mock.get(f"{MOCK_URL}/v2/people/vap", json=mock_response) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) result = list_most_attacked_users_command(client, "") assert len(result.outputs) == 5 assert result.outputs_prefix == "Proofpoint.Vap" assert result.outputs.get("users")[0].get("identity").get("guid") == "88e36bf359-99e8-7e53-f58a-6df8b430be6d" assert result.outputs.get("totalVapUsers") == 2 def test_get_top_clickers_command(requests_mock): """ Scenario: Retrieves a list of the top clickers in the organization for a given period. Given: - User has provided valid credentials and argument. When: - A get_top_clickers command is called and there is clickers in the response. Then: - Ensure number of items is correct. - Ensure outputs prefix is correct. - Ensure a sample value from the API matches what is generated in the context. """ from ProofpointTAP_v2 import Client, get_top_clickers_command mock_response = json.loads(load_mock_response("top_clickers.json")) requests_mock.get(f"{MOCK_URL}/v2/people/top-clickers", json=mock_response) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) result = get_top_clickers_command(client, "") assert len(result.outputs) == 3 assert result.outputs_prefix == "Proofpoint.Topclickers" assert result.outputs.get("users")[1].get("identity").get("guid") == "b4077fsv0e-3a2e-767f-7315-c049f831cc95" assert result.outputs.get("totalTopClickers") == 2 def test_url_decode(requests_mock): """ Scenario: Decode URLs that have been rewritten by TAP to their original, target URL. Given: - User has provided valid credentials and arguments. When: - A url-decode command is called. Then: - Ensure number of items is correct. - Ensure outputs prefix is correct. - Ensure a sample value from the API matches what is generated in the context. """ from ProofpointTAP_v2 import Client, url_decode_command mock_response = json.loads(load_mock_response("url_decode.json")) requests_mock.post(f"{MOCK_URL}/v2/url/decode", json=mock_response) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) result = url_decode_command(client, "") assert len(result.outputs) == 2 assert result.outputs_prefix == "Proofpoint.URL" assert result.outputs[1].get("decodedUrl") == "http://www.bouncycastle.org/" def test_list_issues_command(requests_mock): """ Scenario: Retrieves events for clicks to malicious URLs permitted and messages delivered in the specified time period. Given: - User has provided valid credentials and arguments. When: - A list_issues command is called and there is clicks and messages in the response. Then: - Ensure number of items is correct. - Ensure outputs prefix is correct. - Ensure a sample value from the API matches what is generated in the context. """ from ProofpointTAP_v2 import Client, list_issues_command requests_mock.get( f"{MOCK_URL}/v2/siem/issues", json={ "queryEndTime": "2021-04-16T14:00:00Z", "messagesDelivered": [MOCK_DELIVERED_MESSAGE], "clicksPermitted": [MOCK_PERMITTED_CLICK], }, ) client = Client( proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None ) result = list_issues_command(client, "3 days") messages_result = result[0] clicks_result = result[1] assert len(clicks_result.outputs) == 1 assert clicks_result.outputs_prefix == "Proofpoint.ClicksPermitted" assert clicks_result.outputs[0].get("messageID") == "3333" assert len(messages_result.outputs) == 1 assert messages_result.outputs_prefix == "Proofpoint.MessagesDelivered" assert messages_result.outputs[0].get("messageID") == "1111@evil.zz" @freeze_time("2024-05-03T11:00:00") def test_validate_first_fetch_time_valid_str(): """ Given: - A valid str first_fetch_time When: - running test_module. Then: - No exception is thrown. """ from ProofpointTAP_v2 import validate_first_fetch_time first_fetch_time = "1 day ago" try: validate_first_fetch_time(first_fetch_time) except Exception as e: raise AssertionError(f"validate_first_fetch_time raised an exception {e}") # noqa: PT015 @freeze_time("2024-05-03T11:00:00") def test_validate_first_fetch_time_not_valid(): """ Given: - A first_fetch_time bigger than 7 days ago When: - running test_module. Then: - Exception is thrown. """ from ProofpointTAP_v2 import validate_first_fetch_time first_fetch_time = "8 days ago" try: validate_first_fetch_time(first_fetch_time) except Exception as e: assert ( "The First fetch time range is more than 7 days ago. Please update this parameter since " "Proofpoint supports a maximum 1 week fetch back." ) in str(e) # --------------------------------------------------------------------------- # Look-back ramp-up tests (legacy upgrade safety) # --------------------------------------------------------------------------- # When `look_back_minutes` is enabled but the dedup state (`seen_ids`) is # empty or only freshly initialized, applying the full look-back would cause # events to be re-fetched as duplicates. The integration solves this with a # `look_back_enabled_from` timestamp stored in `last_run`: the effective # look-back grows linearly with the elapsed wall-clock time since that stamp # and is capped at the configured `look_back_minutes`. # These tests assert the effective value passed to `get_fetch_times`. # --------------------------------------------------------------------------- def _spy_get_fetch_times(mocker): """Patch ProofpointTAP_v2.get_fetch_times to capture its arguments while delegating to the real implementation. Returns the spy mock object. """ from ProofpointTAP_v2 import get_fetch_times as _real_get_fetch_times return mocker.patch("ProofpointTAP_v2.get_fetch_times", side_effect=_real_get_fetch_times) def _make_client(): return Client(proofpoint_url=MOCK_URL, api_version="v2", service_principal="user1", secret="123", verify=False, proxies=None) def test_lookback_legacy_instance_disables_lookback_and_stamps(requests_mock, mocker): """ Given: - A legacy instance whose last_run has `last_fetch` but no `seen_ids` key (state from a version of the integration that predates the look-back / seen_ids feature). - look_back_minutes=30 (the new default). When: - fetch_incidents is called. Then: - get_fetch_times is called with look_back_minutes=0 for this cycle (avoiding re-fetching the last 30 minutes as duplicates). - next_run["look_back_enabled_from"] is stamped with the current time so the ramp-up can grow on subsequent fetches. """ last_fetch_time = "2010-01-01T00:00:00Z" current_time = "2010-01-01T00:01:00Z" mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime(current_time, "%Y-%m-%dT%H:%M:%SZ")) spy = _spy_get_fetch_times(mocker) requests_mock.get(MOCK_URL + "/v2/siem/all", json=MOCK_ALL_EVENTS) next_run, _, _ = fetch_incidents( client=_make_client(), last_run={"last_fetch": last_fetch_time}, # no seen_ids -> legacy first_fetch_time="3 days", event_type_filter=ALL_EVENTS, threat_status="", threat_type="", limit=50, look_back_minutes=30, ) # Effective look_back for this fetch must be 0. assert spy.call_args.args[1] == 0 or spy.call_args.kwargs.get("look_back_minutes") == 0 # Stamp persisted for the next cycle. assert next_run.get("look_back_enabled_from") == current_time # seen_ids is initialized in next_run regardless (so on the next fetch # we are no longer "legacy", just "ramping up"). assert "seen_ids" in next_run def test_lookback_rampup_caps_effective_to_elapsed(requests_mock, mocker): """ Given: - An instance previously stamped with look_back_enabled_from=00:00:00. - Current time is 00:10:00 -> elapsed = 10 minutes. - Configured look_back_minutes=30. When: - fetch_incidents is called. Then: - get_fetch_times is called with look_back_minutes=10 (capped to the elapsed window in which seen_ids has actually been tracking events). - The stamp is carried forward in next_run because ramp-up is not done. """ last_fetch_time = "2010-01-01T00:09:00Z" current_time = "2010-01-01T00:10:00Z" enabled_from = "2010-01-01T00:00:00Z" mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime(current_time, "%Y-%m-%dT%H:%M:%SZ")) spy = _spy_get_fetch_times(mocker) requests_mock.get(MOCK_URL + "/v2/siem/all", json=MOCK_ALL_EVENTS) next_run, _, _ = fetch_incidents( client=_make_client(), last_run={ "last_fetch": last_fetch_time, "seen_ids": {}, "look_back_enabled_from": enabled_from, }, first_fetch_time="3 days", event_type_filter=ALL_EVENTS, threat_status="", threat_type="", limit=50, look_back_minutes=30, ) # Effective look-back equals elapsed minutes (10), not the configured 30. passed_look_back = spy.call_args.args[1] if len(spy.call_args.args) >= 2 else spy.call_args.kwargs.get("look_back_minutes") assert passed_look_back == 10 # Stamp is carried forward while ramp-up continues. assert next_run.get("look_back_enabled_from") == enabled_from def test_lookback_rampup_completes_and_drops_stamp(requests_mock, mocker): """ Given: - An instance previously stamped with look_back_enabled_from=00:00:00. - Current time is 01:00:00 -> elapsed = 60 minutes >= look_back_minutes. - Configured look_back_minutes=30. When: - fetch_incidents is called. Then: - get_fetch_times is called with the full configured look_back_minutes=30. - The stamp is dropped from next_run (ramp-up complete, steady state). """ last_fetch_time = "2010-01-01T00:55:00Z" current_time = "2010-01-01T01:00:00Z" enabled_from = "2010-01-01T00:00:00Z" mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime(current_time, "%Y-%m-%dT%H:%M:%SZ")) spy = _spy_get_fetch_times(mocker) requests_mock.get(MOCK_URL + "/v2/siem/all", json=MOCK_ALL_EVENTS) next_run, _, _ = fetch_incidents( client=_make_client(), last_run={ "last_fetch": last_fetch_time, "seen_ids": {}, "look_back_enabled_from": enabled_from, }, first_fetch_time="3 days", event_type_filter=ALL_EVENTS, threat_status="", threat_type="", limit=50, look_back_minutes=30, ) passed_look_back = spy.call_args.args[1] if len(spy.call_args.args) >= 2 else spy.call_args.kwargs.get("look_back_minutes") assert passed_look_back == 30 # Stamp dropped now that ramp-up is complete. assert "look_back_enabled_from" not in next_run def test_lookback_steady_state_uses_full_lookback(requests_mock, mocker): """ Given: - An upgraded instance with last_fetch AND a populated seen_ids, and NO look_back_enabled_from stamp (i.e. steady state). - Configured look_back_minutes=30. When: - fetch_incidents is called. Then: - get_fetch_times is called with the full configured look_back_minutes=30. - No look_back_enabled_from is introduced in next_run. """ last_fetch_time = "2010-01-01T00:00:00Z" current_time = "2010-01-01T00:01:00Z" mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime(current_time, "%Y-%m-%dT%H:%M:%SZ")) spy = _spy_get_fetch_times(mocker) requests_mock.get(MOCK_URL + "/v2/siem/all", json=MOCK_ALL_EVENTS) next_run, _, _ = fetch_incidents( client=_make_client(), last_run={ "last_fetch": last_fetch_time, "seen_ids": {MOCK_DELIVERED_MESSAGE["GUID"]: "2010-01-01T00:00:00Z"}, }, first_fetch_time="3 days", event_type_filter=ALL_EVENTS, threat_status="", threat_type="", limit=50, look_back_minutes=30, ) passed_look_back = spy.call_args.args[1] if len(spy.call_args.args) >= 2 else spy.call_args.kwargs.get("look_back_minutes") assert passed_look_back == 30 assert "look_back_enabled_from" not in next_run def test_lookback_first_fetch_uses_full_lookback(requests_mock, mocker): """ Given: - A first-time fetch (empty last_run, no last_fetch, no seen_ids). - Configured look_back_minutes=30. When: - fetch_incidents is called. Then: - get_fetch_times is called with the full configured look_back_minutes=30 (first fetches have nothing prior to duplicate, so ramp-up is unneeded). - No look_back_enabled_from is stamped in next_run. """ current_time = "2010-01-01T00:05:00Z" mocker.patch("ProofpointTAP_v2.get_now", return_value=datetime.strptime(current_time, "%Y-%m-%dT%H:%M:%SZ")) mocker.patch("ProofpointTAP_v2.parse_date_range", return_value=("2010-01-01T00:00:00Z", "never mind")) spy = _spy_get_fetch_times(mocker) requests_mock.get(MOCK_URL + "/v2/siem/all", json=MOCK_ALL_EVENTS) next_run, _, _ = fetch_incidents( client=_make_client(), last_run={}, # first fetch first_fetch_time="30 minutes", event_type_filter=ALL_EVENTS, threat_status="", threat_type="", limit=50, look_back_minutes=30, ) passed_look_back = spy.call_args.args[1] if len(spy.call_args.args) >= 2 else spy.call_args.kwargs.get("look_back_minutes") assert passed_look_back == 30 assert "look_back_enabled_from" not in next_run