Cortex XDR - IR
Cortex XDR is the world's first detection and response app that natively integrates network, endpoint, and cloud data to stop sophisticated attacks.
Endpoint · Cortex XDR by Palo Alto Networks
Details
| ID | Cortex XDR - IR |
|---|---|
| Provider | Palo Alto Networks |
| Category | Endpoint |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix |
README
Cortex XDR is the world’s first detection and response app that natively integrates network, endpoint, and cloud data to stop sophisticated attacks.
This integration was integrated and tested with version 2.6.5 of Cortex XDR - IR.
Configure Palo Alto Networks Cortex XDR - Investigation and Response on Cortex XSOAR
- Navigate to Settings > Integrations > Servers & Services.
- Search for Palo Alto Networks Cortex XDR - Investigation and Response.
- Click Add instance to create and configure a new integration instance.
| Parameter | Description | Required |
|---|---|---|
| Fetch incidents | False | |
| Incident type | False | |
| Server URL (copy URL from XDR) | True | |
| API Key ID | False | |
| API Key | False | |
| Remove legacy incident fields | Not selected for backwards compatibility. Recommended to select. This will remove duplicated incident fields under file_artifacts, network_artifacts, and alerts (like client_id, clientid.) | False |
| Incident Mirroring Direction | Not supported on Cortex platform. | False |
| Close Mirrored XSOAR Incident | When selected, closing the Cortex XDR incident is mirrored in Cortex XSOAR. | False |
| Close Mirrored Cortex XDR Incident | When selected, closing the Cortex XSOAR incident is mirrored in Cortex XDR. Notice: If not selected, but ‘Close all related alerts in XDR’ is selected, the incident will automatically be closed in Cortex XDR. | False |
| XDR mirroring delay in minutes | In the event of a delay in mirroring incoming changes from XDR, use the xdr_delay parameter to extend the look-back period. However, be aware that this may result in increased latency when updating incidents. | False |
| Custom close-reason mapping (XSOAR -> XDR mirrored incident. Overwrites default close-reason mapping defined by Cortex XSOAR) | Define how to close the mirrored incidents from Cortex XSOAR into Cortex XDR with a custom close reason mapping. Enter a comma-separated list of close reasons (acceptable format {Cortex XSOAR close reason}={Cortex XDR close reason}) to override the default close reason mapping defined by Cortex XSOAR. Note that the mapping must be configured accordingly with the existing close reasons in Cortex XSOAR and Cortex XDR. Not following this format will result in closing the incident with a default close reason. Example: “Resolved=Other,Duplicate=Other”. Refer to ../README.md for possible close-reasons - `XDR Incident Mirroring`. | False |
| Custom close-reason mapping (XDR -> XSOAR mirrored incident. Overwrites default close-reason mapping defined by Cortex XSOAR) | Define how to close the mirrored incidents from Cortex XDR into Cortex XSOAR with a custom close reason mapping. Enter a comma-separated list of close reasons (acceptable format {Cortex XDR close reason}={Cortex XSOAR close reason}) to override the default close reason mapping defined by Cortex XSOAR. Note that the mapping must be configured accordingly with the existing close reasons in Cortex XSOAR and Cortex XDR. Not following this format will result in closing the incident with a default close reason. Example: “Known Issue=Resolved, Duplicate Incident=Other”. Refer to ../README.md for possible close-reasons - `XDR Incident Mirroring`. | False |
| HTTP Timeout | The timeout of the HTTP requests sent to Cortex XDR API (in seconds). | False |
| Maximum number of incidents per fetch | The maximum number of incidents per fetch. Cannot exceed 100. | False |
| Only fetch starred incidents | False | |
| Starred incidents fetch window | Starred fetch window timestamp (<number> <time unit>, e.g., 12 hours, 7 days). Fetches only starred incidents within the specified time range. | False |
| First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days) | False | |
| Sync Incident Owners | For Cortex XSOAR version 6.0.0 and above. If selected, for every incident fetched from Cortex XDR to Cortex XSOAR, the incident owners will be synced. Note that once this value is changed and synchronized between the systems, additional changes will not be reflected. For example, if you change the owner in Cortex XSOAR, the new owner will also be changed in Cortex XDR. However, if you now change the owner back in Cortex XDR, this additional change will not be reflected in Cortex XSOAR. In addition, for this change to be reflected, the owners must exist in both Cortex XSOAR and Cortex XDR. | False |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False | |
| Prevent Only Mode | Whether the XDR tenant mode is prevent only | False |
| Incident Statuses to Fetch | The statuses of the incidents that will be fetched. If no status is provided then incidents of all the statuses will be fetched. Note: An incident whose status was changed to a filtered status after its creation time will not be fetched. | False |
| Minimize Incident Information | Whether to fetch only the essential incident’s fields - without Network Artifacts and File Artifacts to minimize the incident’s information. | False |
| Minimize Alert Information | Whether to fetch only the essential alert fields in order to minimize the incident’s information. Possible values: null_values to remove all null values from alerts data, or any other field of an alert. | False |
| Close all related alerts in XDR | Close all related alerts in Cortex XDR once an incident has been closed in Cortex XSOAR. | False |
- Click Test to validate the URLs, token, and connection.
Configuration
To configure the integration on Cortex XSOAR, you need to generate an API Key and obtain your Cortex XDR URL.
Generate an API Key and API Key ID
- In Cortex XDR, navigate to Settings > Configurations > API Keys.
- Click +New Key and generate an Advanced key.
- Copy the generated API Key and the Key ID from the table.
Note 1: You can assign a custom or built-in role to the API Key. Instance Admin provides the highest privileges, while Privileged Responder offers maximum command execution with fewer overall permissions. In order for the integration test to pass, the API Key must have View permissions for Cases and Issues.
Note 2: If you experience missing updates when mirroring incoming changes from XDR, increase the XDR mirroring delay in minutes parameter. Note that this may increase latency when updating incidents.
URL
- In Cortex XDR, navigate to Settings > Configurations > API Keys.
- Click Copy URL in the top right corner.
XDR & XSOAR
Playbooks
Cortex XDR Incident Handling
The playbook syncs and updates new Cortex XDR alerts that construct the incident.
It enriches indicators using Threat Intelligence integrations and Palo Alto Networks
AutoFocus. The incident’s severity is then updated based on the indicators reputation
and an analyst is assigned for manual investigation. If chosen, automated remediation
with Palo Alto Networks FireWall is initiated. After a manual review by the
SOC analyst, the Cortex XDR incident is closed automatically.
To utilize this playbook for handling Cortex XDR incidents, the classifier that should be selected is Cortex XDR - Classifier.
The selected Mapper (incoming) should be XDR - Incoming Mapper, and the selected Mapper (outgoing) should be Cortex XDR - Outgoing Mapper.
Cortex XDR Lite - Incident Handling
This playbook is a lite default playbook to handle Cortex XDR incidents, and it doesn’t require additional integrations to run. The playbook is triggered by fetching a Palo Alto Networks Cortex XDR incident. First, the playbook performs enrichment on the incident’s indicators. Then, the playbook performs investigation and analysis on the command line and searches for related Cortex XDR alerts by Mitre tactics to identify malicious activity performed on the endpoint and by the user. Based on the enrichment and the investigation results, the playbooks sets the verdict of the incident. If malicious indicators are found, the playbook takes action to block these indicators and isolate the affected endpoint to prevent further damage or the spread of threats. If the verdict is not determined, it lets the analyst decide whether to continue to the remediation stage or close the investigation as benign. As part of this playbook, you’ll receive a comprehensive layout that presents incident details, analysis, investigation findings, and the final verdict. Additionally, the layout offers convenient remediation buttons for quicker manual actions.
To utilize this playbook for handling XDR incidents, the classifier should be empty, and the selected incident type should be Cortex XDR - Lite.
The selected Mapper (incoming) should be XDR - Incoming Mapper, and the selected Mapper (outgoing) should be Cortex XDR - Outgoing Mapper.
Use Cases
- Fetch incidents from Cortex XDR
- Enrich incident with alerts and incident from Cortex XDR
- Update incident in Cortex XDR
- Search for endpoints
- Isolate/unisolate endpoints
- Insert parsed alerts into Cortex XDR
- Insert CEF alerts into Cortex XDR
- Query for agent audit reports
- Query for audit management logs
- Create distribution
- Get distribution download URL
- Get distribution versions
Automation
To sync incidents between Cortex XSOAR and Cortex XDR, you should use the XDRSyncScript script, which you can find in the automation page.
Fetched Incidents Data
incident_id:31
creation_time:1564594008755
modification_time:1566339537617
detection_time:null
status:new
severity:low
description:6 'Microsoft Windows RPC Fragment Evasion Attempt' alerts detected by PAN NGFW on 6 hosts
assigned_user_mail:null
assigned_user_pretty_name:null
alert_count:6
low_severity_alert_count:0
med_severity_alert_count:6
high_severity_alert_count:0
user_count:1
host_count:6
notes:null
resolve_comment:null
manual_severity:low
manual_description:null
xdr_url:https://1111.paloaltonetworks.com/incident-view/31
XDR Incident Mirroring
Note this feature is available from Cortex XSOAR version 6.0.0
You can enable incident mirroring between Cortex XSOAR incidents and Cortex XDR incidents.
To setup the mirroring follow these instructions:
- Navigate to Settings > Integrations > Servers & Services.
- Search for Cortex XDR - IR and select your integration instance.
- Enable Fetches incidents.
- Under Mapper (incoming), select
XDR - Incoming Mapper. - Under Mapper (outgoing), select
Cortex XDR - Outgoing Mapper. - In the Incident Mirroring Direction integration parameter, select in which direction the incidents should be mirrored:
- Incoming - Any changes in Cortex XDR incidents will be reflected in Cortex XSOAR incidents.
- Outgoing - Any changes in Cortex XSOAR incidents will be reflected in Cortex XDR incidents.
- Both - Changes in Cortex XSOAR and Cortex XDR incidents will be reflected in both directions.
- None - Choose this to turn off incident mirroring.
-
Optional: Provide a custom close-reason mapping for mirrored XDR <-> XSOAR incidents. Please use only possible close-reasons to map:
Possible Closure Reasons for Cortex XSOAR Incident Resolved False Positive Duplicate Security Testing Other Possible Closure Reasons for Cortex Cortex XDR Incident True Positive False Positive Duplicate Incident Security Testing Known Issue Other Auto Failing to use only available values will result in using default mapping of closure reasons within the mirroring process.
Close-reason default mapping XSOAR -> XDR: Other=Other, Duplicate=Duplicate Incident, False Positive=False Positive, Resolved=True Positive
Close-reason default mapping XDR -> XSOAR: Known Issue=Other, Duplicate Incident=Duplicate, False Positive=False Positive, True Positive=Resolved, Other=Other, Auto=Resolved
-
Optional: Check the Sync Incident Owners integration parameter to sync the incident owners in both Cortex XDR and Cortex XSOAR.
- Note: This feature will only work if the same users are registered in both Cortex XSOAR and Cortex XDR.
-
Newly fetched incidents will be mirrored in the chosen direction.
- Note: This will not effect existing incidents.
XDR Mirroring Notes, limitations and Troubleshooting
- While you can mirror changes in incident fields both in and out in each incident, you can only mirror in a single direction at a time. For example:
If we have an incident with two fields (A and B) in Cortex XDR and Cortex XSOAR while Incoming And Outgoing mirroring is selected:- I can mirror field A from Cortex XDR to Cortex XSOAR and field B from Cortex XSOAR to Cortex XDR.
- I cannot mirror changes from field A in both directions.
Initially all fields are mirrored in from Cortex XDR to Cortex XSOAR. Once they are changed in Cortex XSOAR, they can only be mirrored out.
-
Do not use the
XDRSyncScriptautomation nor any playbook that uses this automation
(e.gCortex XDR Incident SyncorCortex XDR incident handling v2), as it impairs the mirroring functionality. - When migrating an existing instance to the mirroring feature, or in case the mirroring does not work as expected, make sure that:
- The default playbook of the Cortex XDR Incident incident type is not Cortex XDR Incident Sync, change it to a
different playbook that does not useXDRSyncScript. - The Cortex XDR integration instance incoming mapper is set to
Cortex XDR - Incoming Mapperand the outgoing mapper is set toCortex XDR - Outgoing Mapper. - Mirroring impacts only incidents that were fetched after the mirroring was enabled for this instance. If incidents were fetched with the incorrect mapper, changing the mapper will not affect them. This can be resolved by resetting the last fetch run and re-fetching the incidents. New incidents will be created and the old ones will no longer be relevant.
- The default playbook of the Cortex XDR Incident incident type is not Cortex XDR Incident Sync, change it to a
-
The API includes a limit rate of 10 API requests per minute. Therefore, in a case of a limit rate exception, the sync loop will stop and will resume from the last incident.
OwnerandcloseReasonmappings are done using the integration code, therefore they are not part of the out-of-the-box mapper and should not be specified in any future mapper.
Fetch Behavior vs Mirroring
Note: All incidents, including those with a “resolved” status, will be fetched into Cortex XSOAR as “active” incidents to enable the execution of our automations. However, the original resolved status of the incidents will be preserved in the incident details. If you prefer to keep certain incidents closed, you can utilize the “Incident Statuses to Fetch” filter during the configuration stage and choose not to import those specific incidents. Alternatively, you can utilize pre-processing rules to define specific types of incidents to be imported as closed.
Regarding mirroring, if you have already imported an incident and the mirroring feature is enabled, changing the incident’s status to resolved on the Cortex XDR platform will trigger the mirroring process, resulting in the closure of the incident in Cortex XSOAR.
Commands
You can execute these commands from the Cortex XSOAR 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.
xdr-get-incidents (Deprecated)
This command is deprecated please use xdr-case-list instead. Returns a list of incidents, which you can filter by a list of incident IDs (max. 100), the time the incident was last modified, and the time the incident was created.
If you pass multiple filtering arguments, they will be concatenated using the AND condition. The OR condition is not supported.
Required Permissions
Required Permissions For API call:
Alerts And Incidents –> View
Builtin Roles with this permission includes: “Investigator”, “Responder”, “Privileged Investigator”, “Privileged Responder”, “Viewer”, and “Instance Admin”.
Base Command
xdr-get-incidents
Input
| Argument Name | Description | Required |
|---|---|---|
| lte_creation_time | A date in the format 2019-12-31T23:59:00 in UTC. Only incidents that were created on or before the specified date/time will be retrieved. | Optional |
| gte_creation_time | A date in the format 2019-12-31T23:59:00 in UTC. Only incidents that were created on or after the specified date/time will be retrieved. | Optional |
| lte_modification_time | Filters returned incidents that were created on or before the specified date/time, in the format 2019-12-31T23:59:00. | Optional |
| gte_modification_time | Filters returned incidents that were modified on or after the specified date/time, in the format 2019-12-31T23:59:00. | Optional |
| incident_id_list | An array or CSV string of incident IDs. | Optional |
| since_creation_time | Filters returned incidents that were created on or after the specified date/time range, for example, 1 month, 2 days, 1 hour, and so on. | Optional |
| since_modification_time | Filters returned incidents that were modified on or after the specified date/time range, for example, 1 month, 2 days, 1 hour, and so on. | Optional |
| sort_by_modification_time | Sorts returned incidents by the date/time that the incident was last modified (“asc” - ascending, “desc” - descending). Possible values are: asc, desc. | Optional |
| sort_by_creation_time | Sorts returned incidents by the date/time that the incident was created (“asc” - ascending, “desc” - descending). Possible values are: asc, desc. | Optional |
| page | Page number (for pagination). The default is 0 (the first page). Default is 0. | Optional |
| limit | Maximum number of incidents to return per page. The default and maximum is 100. Default is 100. | Optional |
| status | Filters only incidents in the specified status. The options are: new, under_investigation, resolved_known_issue, resolved_false_positive, resolved_true_positive resolved_security_testing, resolved_other, resolved_auto, resolved_auto_resolve. | Optional |
| starred | Whether the incident is starred (Boolean value: true or false). Possible values are: true, false. | Optional |
| starred_incidents_fetch_window | Starred fetch window timestamp (<number> <time unit>, e.g., 12 hours, 7 days). Default is 3 days. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.Incident.incident_id | String | Unique ID assigned to each returned incident. |
| PaloAltoNetworksXDR.Incident.manual_severity | String | Incident severity assigned by the user. This does not affect the calculated severity. Can be “low”, “medium”, “high” |
| PaloAltoNetworksXDR.Incident.manual_description | String | Incident description provided by the user. |
| PaloAltoNetworksXDR.Incident.assigned_user_mail | String | Email address of the assigned user. |
| PaloAltoNetworksXDR.Incident.high_severity_alert_count | String | Number of alerts with the severity HIGH. |
| PaloAltoNetworksXDR.Incident.host_count | number | Number of hosts involved in the incident. |
| PaloAltoNetworksXDR.Incident.xdr_url | String | A link to the incident view on Cortex XDR. |
| PaloAltoNetworksXDR.Incident.assigned_user_pretty_name | String | Full name of the user assigned to the incident. |
| PaloAltoNetworksXDR.Incident.alert_count | number | Total number of alerts in the incident. |
| PaloAltoNetworksXDR.Incident.med_severity_alert_count | number | Number of alerts with the severity MEDIUM. |
| PaloAltoNetworksXDR.Incident.user_count | number | Number of users involved in the incident. |
| PaloAltoNetworksXDR.Incident.severity | String | Calculated severity of the incident. Valid values are: “low”,”medium”,”high” |
| PaloAltoNetworksXDR.Incident.low_severity_alert_count | String | Number of alerts with the severity LOW. |
| PaloAltoNetworksXDR.Incident.status | String | Current status of the incident. Valid values are: “new”,”under_investigation”,”resolved_known_issue”,”resolved_duplicate”,”resolved_false_positive”,”resolved_true_positive”,”resolved_security_testing” or “resolved_other”. |
| PaloAltoNetworksXDR.Incident.description | String | Dynamic calculated description of the incident. |
| PaloAltoNetworksXDR.Incident.resolve_comment | String | Comments entered by the user when the incident was resolved. |
| PaloAltoNetworksXDR.Incident.notes | String | Comments entered by the user regarding the incident. |
| PaloAltoNetworksXDR.Incident.creation_time | date | Date and time the incident was created on Cortex XDR. |
| PaloAltoNetworksXDR.Incident.detection_time | date | Date and time that the first alert occurred in the incident. |
| PaloAltoNetworksXDR.Incident.modification_time | date | Date and time that the incident was last modified. |
Command Example
!xdr-get-incidents gte_creation_time=2010-10-10T00:00:00 limit=3 sort_by_creation_time=desc
Context Example
{
"PaloAltoNetworksXDR.Incident": [
{
"host_count": 1,
"incident_id": "4",
"manual_severity": "medium",
"description": "5 'This alert from content TestXDRPlaybook' alerts detected by Checkpoint - SandBlast ",
"severity": "medium",
"modification_time": 1579290004178,
"assigned_user_pretty_name": null,
"notes": null,
"creation_time": 1577276587937,
"alert_count": 5,
"med_severity_alert_count": 1,
"detection_time": null,
"assigned_user_mail": null,
"resolve_comment": "This issue was solved in Incident number 192304",
"status": "new",
"user_count": 1,
"xdr_url": "https://some.xdr.url.com/incident-view/4",
"starred": false,
"low_severity_alert_count": 0,
"high_severity_alert_count": 4,
"manual_description": null
},
{
"host_count": 1,
"incident_id": "3",
"manual_severity": "medium",
"description": "'test 1' generated by Virus Total - Firewall",
"severity": "medium",
"modification_time": 1579237974014,
"assigned_user_pretty_name": "woo@test.com",
"notes": null,
"creation_time": 1576100096594,
"alert_count": 1,
"med_severity_alert_count": 0,
"detection_time": null,
"assigned_user_mail": "woo@test.com",
"resolve_comment": null,
"status": "new",
"user_count": 1,
"xdr_url": "https://some.xdr.url.com/incident-view/3",
"starred": false,
"low_severity_alert_count": 0,
"high_severity_alert_count": 1,
"manual_description": null
},
{
"host_count": 1,
"incident_id": "2",
"manual_severity": "high",
"description": "'Alert Name Example 333' along with 1 other alert generated by Virus Total - VPN & Firewall-3 and Checkpoint - SandBlast",
"severity": "high",
"modification_time": 1579288790259,
"assigned_user_pretty_name": null,
"notes": null,
"creation_time": 1576062816474,
"alert_count": 2,
"med_severity_alert_count": 0,
"detection_time": null,
"assigned_user_mail": null,
"resolve_comment": null,
"status": "under_investigation",
"user_count": 1,
"xdr_url": "https://some.xdr.url.com/incident-view/2",
"starred": false,
"low_severity_alert_count": 0,
"high_severity_alert_count": 2,
"manual_description": null
}
]
}
Human Readable Output
Incidents
alert_count assigned_user_mail assigned_user_pretty_name creation_time description detection_time high_severity_alert_count host_count incident_id low_severity_alert_count manual_description manual_severity med_severity_alert_count modification_time notes resolve_comment severity starred status user_count xdr_url 5 1577276587937 5 ‘This alert from content TestXDRPlaybook’ alerts detected by Checkpoint - SandBlast 4 1 4 0 medium 1 1579290004178 This issue was solved in Incident number 192304 medium false new 1 https://some.xdr.url.com/incident-view/41 woo@test.com woo@test.com 1576100096594 ‘test 1’ generated by Virus Total - Firewall 1 1 3 0 medium 0 1579237974014 medium false new 1 https://some.xdr.url.com/incident-view/32 1576062816474 ‘Alert Name Example 333’ along with 1 other alert generated by Virus Total - VPN & Firewall-3 and Checkpoint - SandBlast 2 1 2 0 high 0 1579288790259 high false under_investigation 1 https://some.xdr.url.com/incident-view/2
xdr-get-incident-extra-data (Deprecated)
This command is deprecated. Returns additional data for the specified incident, for example, related alerts, file artifacts, network artifacts, and so on.
Required Permissions
Required Permissions For API call:
Alerts And Incidents –> View
Builtin Roles with this permission includes: “Investigator”, “Responder”, “Privileged Investigator”, “Privileged Responder”, “Viewer”, and “Instance Admin”.
Base Command
xdr-get-incident-extra-data
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The ID of the incident for which to get additional data. | Required |
| alerts_limit | Maximum number of alerts to return. Default is 1000. | Optional |
| return_only_updated_incident | Return data only if the incident was changed since the last time it was mirrored into Cortex XSOAR. This flag should be used only from within a Cortex XDR incident. Default is False. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.Incident.incident_id | String | Unique ID assigned to each returned incident. |
| PaloAltoNetworksXDR.Incident.creation_time | Date | Date and time the incident was created on Cortex XDR. |
| PaloAltoNetworksXDR.Incident.modification_time | Date | Date and time that the incident was last modified. |
| PaloAltoNetworksXDR.Incident.detection_time | Date | Date and time that the first alert occurred in the incident. |
| PaloAltoNetworksXDR.Incident.status | String | Current status of the incident. Valid values are: |
| “new”,”under_investigation”,”resolved_known_issue”,”resolved_duplicate”,”resolved_false_positive”,”resolved_true_positive”,”resolved_security_testing”,”resolved_other” | ||
| PaloAltoNetworksXDR.Incident.severity | String | Calculated severity of the incident. Valid values are: “low”,”medium”,”high” |
| PaloAltoNetworksXDR.Incident.description | String | Dynamic calculated description of the incident. |
| PaloAltoNetworksXDR.Incident.assigned_user_mail | String | Email address of the assigned user. |
| PaloAltoNetworksXDR.Incident.assigned_user_pretty_name | String | Full name of the user assigned to the incident. |
| PaloAltoNetworksXDR.Incident.alert_count | Number | Total number of alerts in the incident. |
| PaloAltoNetworksXDR.Incident.low_severity_alert_count | Number | Number of alerts with the severity LOW. |
| PaloAltoNetworksXDR.Incident.med_severity_alert_count | Number | Number of alerts with the severity MEDIUM. |
| PaloAltoNetworksXDR.Incident.high_severity_alert_count | Number | Number of alerts with the severity HIGH. |
| PaloAltoNetworksXDR.Incident.user_count | Number | Number of users involved in the incident. |
| PaloAltoNetworksXDR.Incident.host_count | Number | Number of hosts involved in the incident |
| PaloAltoNetworksXDR.Incident.notes | Unknown | Comments entered by the user regarding the incident. |
| PaloAltoNetworksXDR.Incident.resolve_comment | String | Comments entered by the user when the incident was resolved. |
| PaloAltoNetworksXDR.Incident.manual_severity | String | Incident severity assigned by the user. This does not affect the calculated severity of low, medium, or high. |
| PaloAltoNetworksXDR.Incident.manual_description | String | Incident description provided by the user. |
| PaloAltoNetworksXDR.Incident.xdr_url | String | A link to the incident view on Cortex XDR. |
| PaloAltoNetworksXDR.Incident.starred | Boolean | Incident starred. |
| PaloAltoNetworksXDR.Incident.wildfire_hits.mitre_techniques_ids_and_names | String | Incident Mitre techniques IDs and names. |
| PaloAltoNetworksXDR.Incident.wildfire_hits.mitre_tactics_ids_and_names | String | Incident Mitre tactics ids and names. |
| PaloAltoNetworksXDR.Incident.alerts.alert_id | String | Unique ID for each alert. |
| PaloAltoNetworksXDR.Incident.alerts.detection_timestamp | Date | Date and time that the alert occurred. |
| PaloAltoNetworksXDR.Incident.alerts.source | String | Source of the alert. The product/vendor this alert came from. |
| PaloAltoNetworksXDR.Incident.alerts.severity | String | Severity of the alert.Valid values are: “low”,”medium”,”high””” |
| PaloAltoNetworksXDR.Incident.alerts.name | String | Calculated name of the alert. |
| PaloAltoNetworksXDR.Incident.alerts.category | String | Category of the alert, for example, Spyware Detected via Anti-Spyware profile. |
| PaloAltoNetworksXDR.Incident.alerts.description | String | Textual description of the alert. |
| PaloAltoNetworksXDR.Incident.alerts.host_ip_list | Unknown | Host IP involved in the alert. |
| PaloAltoNetworksXDR.Incident.alerts.host_name | String | Host name involved in the alert. |
| PaloAltoNetworksXDR.Incident.alerts.user_name | String | User name involved with the alert. |
| PaloAltoNetworksXDR.Incident.alerts.event_type | String | Event type. Valid values are: “Process Execution”,”Network Event”,”File Event”,”Registry Event”,”Injection Event”,”Load Image Event”,”Windows Event Log” |
| PaloAltoNetworksXDR.Incident.alerts.action | String | The action that triggered the alert. Valid values are: “REPORTED”, “BLOCKED”, “POST_DETECTED”, “SCANNED”, “DOWNLOAD”, “PROMPT_ALLOW”, “PROMPT_BLOCK”, “DETECTED”, “BLOCKED_1”, “BLOCKED_2”, “BLOCKED_3”, “BLOCKED_5”, “BLOCKED_6”, “BLOCKED_7”, “BLOCKED_8”, “BLOCKED_9”, “BLOCKED_10”, “BLOCKED_11”, “BLOCKED_13”, “BLOCKED_14”, “BLOCKED_15”, “BLOCKED_16”, “BLOCKED_17”, “BLOCKED_24”, “BLOCKED_25”, “DETECTED_0”, “DETECTED_4”, “DETECTED_18”, “DETECTED_19”, “DETECTED_20”, “DETECTED_21”, “DETECTED_22”, “DETECTED_23” |
| PaloAltoNetworksXDR.Incident.alerts.action_pretty | String | The action that triggered the alert. Valid values are: “Detected (Reported)” “Prevented (Blocked)” “Detected (Post Detected)” “Detected (Scanned)” “Detected (Download)” “Detected (Prompt Allow)” “Prevented (Prompt Block)” “Detected” “Prevented (Denied The Session)” “Prevented (Dropped The Session)” “Prevented (Dropped The Session And Sent a TCP Reset)” “Prevented (Blocked The URL)” “Prevented (Blocked The IP)” “Prevented (Dropped The Packet)” “Prevented (Dropped All Packets)” “Prevented (Terminated The Session And Sent a TCP Reset To Both Sides Of The Connection)” “Prevented (Terminated The Session And Sent a TCP Reset To The Client)” “Prevented (Terminated The Session And Sent a TCP Reset To The Server)” “Prevented (Continue)” “Prevented (Block-Override)” “Prevented (Override-Lockout)” “Prevented (Override)” “Prevented (Random-Drop)” “Prevented (Silently Dropped The Session With An ICMP Unreachable Message To The Host Or Application)” “Prevented (Block)” “Detected (Allowed The Session)” “Detected (Raised An Alert)” “Detected (Syncookie Sent)” “Detected (Forward)” “Detected (Wildfire Upload Success)” “Detected (Wildfire Upload Failure)” “Detected (Wildfire Upload Skip)” “Detected (Sinkhole)” |
| PaloAltoNetworksXDR.Incident.alerts.actor_process_image_name | String | Image name. |
| PaloAltoNetworksXDR.Incident.alerts.actor_process_command_line | String | Command line. |
| PaloAltoNetworksXDR.Incident.alerts.actor_process_signature_status | String | Signature status. Valid values are: “Signed” “Invalid Signature” “Unsigned” “Revoked” “Signature Fail” “N/A” “Weak Hash”. |
| PaloAltoNetworksXDR.Incident.alerts.actor_process_signature_vendor | String | Signature vendor name. |
| PaloAltoNetworksXDR.Incident.alerts.causality_actor_process_image_name | String | Image name. |
| PaloAltoNetworksXDR.Incident.alerts.causality_actor_process_command_line | String | Command line. |
| PaloAltoNetworksXDR.Incident.alerts.causality_actor_process_signature_status | String | Signature status. Valid values are: “Signed” “Invalid Signature” “Unsigned” “Revoked” “Signature Fail” “N/A” “Weak Hash” |
| PaloAltoNetworksXDR.Incident.alerts.causality_actor_process_signature_vendor | String | Signature vendor. |
| PaloAltoNetworksXDR.Incident.alerts.causality_actor_causality_id | Unknown | Causality ID. |
| PaloAltoNetworksXDR.Incident.alerts.action_process_image_name | String | Image name. |
| PaloAltoNetworksXDR.Incident.alerts.action_process_image_command_line | String | Command line. |
| PaloAltoNetworksXDR.Incident.alerts.action_process_image_sha256 | String | Image SHA256. |
| PaloAltoNetworksXDR.Incident.alerts.action_process_signature_status | String | Signature status. Valid values are: “Signed” “Invalid Signature” “Unsigned” “Revoked” “Signature Fail” “N/A” “Weak Hash” |
| PaloAltoNetworksXDR.Incident.alerts.action_process_signature_vendor | String | Signature vendor name. |
| PaloAltoNetworksXDR.Incident.alerts.action_file_path | String | File path. |
| PaloAltoNetworksXDR.Incident.alerts.action_file_md5 | String | File MD5. |
| PaloAltoNetworksXDR.Incident.alerts.action_file_sha256 | String | File SHA256. |
| PaloAltoNetworksXDR.Incident.alerts.action_registry_data | String | Registry data. |
| PaloAltoNetworksXDR.Incident.alerts.action_registry_full_key | String | Registry full key. |
| PaloAltoNetworksXDR.Incident.alerts.action_local_ip | String | Local IP. |
| PaloAltoNetworksXDR.Incident.alerts.action_local_port | Number | Local port. |
| PaloAltoNetworksXDR.Incident.alerts.action_remote_ip | String | Remote IP. |
| PaloAltoNetworksXDR.Incident.alerts.action_remote_port | Number | Remote port. |
| PaloAltoNetworksXDR.Incident.alerts.action_external_hostname | String | External hostname. |
| PaloAltoNetworksXDR.Incident.alerts.fw_app_id | Unknown | Firewall app id. |
| PaloAltoNetworksXDR.Incident.alerts.is_whitelisted | String | Is the alert on allow list. Valid values are: “Yes” “No” |
| PaloAltoNetworksXDR.Incident.alerts.starred | Boolean | Alert starred. |
| PaloAltoNetworksXDR.Incident.network_artifacts.type | String | Network artifact type. |
| PaloAltoNetworksXDR.Incident.network_artifacts.network_remote_port | number | The remote port related to the artifact. |
| PaloAltoNetworksXDR.Incident.network_artifacts.alert_count | number | Number of alerts related to the artifact. |
| PaloAltoNetworksXDR.Incident.network_artifacts.network_remote_ip | String | The remote IP related to the artifact. |
| PaloAltoNetworksXDR.Incident.network_artifacts.is_manual | boolean | Whether the artifact was created by the user (manually). |
| PaloAltoNetworksXDR.Incident.network_artifacts.network_domain | String | The domain related to the artifact. |
| PaloAltoNetworksXDR.Incident.network_artifacts.type | String | The artifact type. Valid values are: “META”, “GID”, “CID”, “HASH”, “IP”, “DOMAIN”, “REGISTRY”, “HOSTNAME” |
| PaloAltoNetworksXDR.Incident.network_artifacts.network_country | String | The country related to the artifact. |
| PaloAltoNetworksXDR.Incident.file_artifacts.file_signature_status | String | Digital signature status of the file. Valid values are: “SIGNATURE_UNAVAILABLE” “SIGNATURE_SIGNED” “SIGNATURE_INVALID” “SIGNATURE_UNSIGNED” “SIGNATURE_WEAK_HASH” |
| PaloAltoNetworksXDR.Incident.file_artifacts.is_process | boolean | Whether the file artifact is related to a process execution. |
| PaloAltoNetworksXDR.Incident.file_artifacts.file_name | String | Name of the file. |
| PaloAltoNetworksXDR.Incident.file_artifacts.file_wildfire_verdict | String | The file verdict, calculated by Wildfire. Valid values are: “BENIGN” “MALWARE” “GRAYWARE” “PHISHING” “UNKNOWN”. |
| PaloAltoNetworksXDR.Incident.file_artifacts.alert_count | number | Number of alerts related to the artifact. |
| PaloAltoNetworksXDR.Incident.file_artifacts.is_malicious | boolean | Whether the artifact is malicious, as decided by the Wildfire verdict. |
| PaloAltoNetworksXDR.Incident.file_artifacts.is_manual | boolean | Whether the artifact was created by the user (manually). |
| PaloAltoNetworksXDR.Incident.file_artifacts.type | String | The artifact type. Valid values are: “META” “GID” “CID” “HASH” “IP” “DOMAIN” “REGISTRY” “HOSTNAME” |
| PaloAltoNetworksXDR.Incident.file_artifacts.file_sha256 | String | SHA256 hash of the file. |
| PaloAltoNetworksXDR.Incident.file_artifacts.file_signature_vendor_name | String | File signature vendor name. |
| Account.Username | String | The username in the relevant system. |
| Endpoint.Hostname | String | The hostname that is mapped to this endpoint. |
| Endpoint.ID | String | The agent ID of the endpoint. |
| File.Path | String | The path where the file is located. |
| File.MD5 | String | The MD5 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Name | String | The full file name (including file extension). |
| Process.Name | String | The name of the process. |
| Process.MD5 | String | The MD5 hash of the process. |
| Process.SHA256 | String | The SHA256 hash of the process. |
| Process.PID | String | The PID of the process. |
| Process.Path | String | The file system path to the binary file. |
| Process.Start Time | String | The timestamp of the process start time. |
| Process.CommandLine | String | The full command line (including arguments). |
| Process.is_malicious | boolean | Whether the artifact is malicious, as decided by the Wildfire verdict. |
| IP.Address | String | IP address. |
| IP.Geo.Country | String | The country in which the IP address is located. |
| Domain.Name | String | The domain name, for example: “google.com”. |
Human Readable Output
Incident 4
alert_count assigned_user_mail assigned_user_pretty_name creation_time description detection_time high_severity_alert_count host_count incident_id low_severity_alert_count manual_description manual_severity med_severity_alert_count modification_time notes resolve_comment severity starred status user_count xdr_url 5 1577276587937 5 ‘This alert from content TestXDRPlaybook’ alerts detected by Checkpoint - SandBlast 4 1 4 0 medium 1 1579290004178 This issue was solved in Incident number 192304 medium false new 1 https://some.xdr.url.com/incident-view/4Alerts
action action_external_hostname action_file_md5 action_file_path action_file_sha256 action_local_ip action_local_port action_pretty action_process_image_command_line action_process_image_name action_process_image_sha256 action_process_signature_status action_process_signature_vendor action_registry_data action_registry_full_key action_remote_ip action_remote_port actor_process_command_line actor_process_image_name actor_process_signature_status actor_process_signature_vendor alert_id category causality_actor_causality_id causality_actor_process_command_line causality_actor_process_image_name causality_actor_process_signature_status causality_actor_process_signature_vendor description detection_timestamp event_type fw_app_id host_ip_list host_name is_whitelisted name severity source starred user_name VALUE_NA,
N/A196.168.0.1 7000 VALUE_NA,
N/AN/A N/A 2.2.2.2 8000 N/A N/A 6 N/A N/A Test - alert generated by Test XDR Playbook 1577276586921 Network Event No Test - alert generated by Test XDR Playbook medium Cisco - Sandblast false VALUE_NA,
N/A196.168.0.111 2000 VALUE_NA,
N/AN/A N/A 2.2.2.2 6000 N/A N/A 7 N/A N/A This alert from content TestXDRPlaybook description 1577776701589 Network Event No This alert from content TestXDRPlaybook high Checkpoint - SandBlast false VALUE_NA,
N/A196.168.0.111 2000 VALUE_NA,
N/AN/A N/A 2.2.2.2 6000 N/A N/A 8 N/A N/A This alert from content TestXDRPlaybook description 1577958479843 Network Event No This alert from content TestXDRPlaybook high Checkpoint - SandBlast false VALUE_NA,
N/A196.168.0.111 2000 VALUE_NA,
N/AN/A N/A 2.2.2.2 6000 N/A N/A 9 N/A N/A This alert from content TestXDRPlaybook description 1578123895414 Network Event No This alert from content TestXDRPlaybook high Checkpoint - SandBlast false VALUE_NA,
N/A196.168.0.111 2000 VALUE_NA,
N/AN/A N/A 2.2.2.2 6000 N/A N/A 10 N/A N/A This alert from content TestXDRPlaybook description 1578927443615 Network Event No This alert from content TestXDRPlaybook high Checkpoint - SandBlast false Network Artifacts
alert_count is_manual network_country network_domain network_remote_ip network_remote_port type 5 false 2.2.2.2 8000 IP File Artifacts
No entries.
xdr-update-incident (Deprecated)
This command is deprecated please use xdr-case-update instead. Updates one or more fields of a specified incident. Missing fields will be ignored. To remove the assignment for an incident, pass a null value in the assignee email argument.
Required Permissions
Required Permissions For API call:
Alerts And Incidents –> View / Edit
Builtin Roles with this permission includes: “Investigator”, “Privileged Investigator”, “Privileged Responder”, and “Instance Admin”.
Base Command
xdr-update-incident
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | XDR incident ID. You can get the incident ID from the output of the ‘xdr-get-incidents’ command or the ‘xdr-get-incident-extra-details’ command. | Required |
| manual_severity | Severity to assign to the incident (LOW, MEDIUM, or HIGH). Possible values are: HIGH, MEDIUM, LOW. | Optional |
| assigned_user_mail | Email address of the user to assign to the incident. | Optional |
| assigned_user_pretty_name | Full name of the user assigned to the incident. To supply a new value in this field, you must also provide a value for the ‘assigned_user_mail’ argument. | Optional |
| status | Status of the incident. Valid values are: NEW, UNDER_INVESTIGATION, RESOLVED_KNOWN_ISSUE, RESOLVED_DUPLICATE, RESOLVED_FALSE_POSITIVE, RESOLVED_TRUE_POSITIVE, RESOLVED_SECURITY_TESTING, RESOLVED_OTHER. Possible values are: NEW, UNDER_INVESTIGATION, RESOLVED_KNOWN_ISSUE, RESOLVED_DUPLICATE, RESOLVED_FALSE_POSITIVE, RESOLVED_TRUE_POSITIVE, RESOLVED_SECURITY_TESTING, RESOLVED_OTHER. | Optional |
| resolve_comment | Comment explaining why the incident was resolved. This should be set when the incident is resolved. | Optional |
| unassign_user | If true, will remove all assigned users from the incident. Possible values are: true. | Optional |
Command Example
!xdr-update-incident incident_id=4
Context Output
There is no context output for this command.
Human Readable Output
Incident 4 has been updated
xdr-insert-parsed-alert (Deprecated)
This command is deprecated. Uploads an alert from external alert sources in Cortex XDR format. Cortex XDR displays alerts that are parsed
successfully in related incidents and views. You can send 600 alerts per minute. Each request can contain a
maximum of 60 alerts.
Required Permissions
Required Permissions For API call:
External Alerts Mapping–> View
Builtin Roles with this permission includes: “Instance Admin”.
Base Command
xdr-insert-parsed-alert
Input
| Argument Name | Description | Required |
|---|---|---|
| product | String value that defines the product. | Required |
| vendor | String value that defines the vendor. | Required |
| local_ip | String value for the source IP address. | Optional |
| local_port | Integer value for the source port. | Required |
| remote_ip | String value of the destination IP address. |
Required |
| remote_port | Integer value for the destination port. |
Required |
| event_timestamp | Integer value representing the time the alert occurred in milliseconds, or a string value in date format 2019-10-23T10:00:00. If not set, the event time will be defined as now. | Optional |
| severity | String value of alert severity. Valid values are: Informational, Low, Medium or High. Possible values are: Informational, Low, Medium, High. Default is Medium. |
Optional |
| alert_name | String defining the alert name. | Required |
| alert_description | String defining the alert description. | Optional |
Context Output
There is no context output for this command.
xdr-insert-cef-alerts (Deprecated)
This command is deprecated. Upload alerts in CEF format from external alert sources. After you map CEF alert fields to Cortex XDR fields, Cortex XDR displays the alerts in related incidents and views. You can send 600 requests per minute. Each request can contain a maximum of 60 alerts.
Required Permissions
Required Permissions For API call:
External Alerts Mapping–> View
Builtin Roles with this permission includes: “Instance Admin”.
Base Command
xdr-insert-cef-alerts
Input
| Argument Name | Description | Required |
|---|---|---|
| cef_alerts | List of alerts in CEF format. | Required |
Context Output
There is no context output for this command.
xdr-endpoint-isolate
Isolates the specified endpoint.
Required Permissions
Required Permissions For API call:
Endpoint Administrations –> View
Action Center –> View/ Edit
Action Center –> Isolate
Builtin Roles with this permission includes: “Privileged Responder” and “Instance Admin”.
Base Command
xdr-endpoint-isolate
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | Allows linking the response action to the incident that triggered it. | Optional |
| endpoint_id | The endpoint ID (string) to isolate. You can retrieve the string from the xdr-get-endpoints command. | Required |
| suppress_disconnected_endpoint_error | Whether to suppress an error when trying to isolate a disconnected endpoint. When sets to false, an error will be returned. Possible values are: true, false. Default is false. | Optional |
| interval_in_seconds | Interval in seconds between each poll. | Optional |
| timeout_in_seconds | Polling timeout in seconds. | Optional |
| action_id | For polling use. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.Isolation.endpoint_id | String | The endpoint ID. |
xdr-endpoint-unisolate
Reverses the isolation of an endpoint.
Required Permissions
Required Permissions For API call:
Endpoint Administrations –> View
Action Center –> View/ Edit
Action Center –> Isolate
Builtin Roles with this permission includes: “Privileged Responder” and “Instance Admin”.
Base Command
xdr-endpoint-unisolate
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | Allows linking the response action to the incident that triggered it. | Optional |
| endpoint_id | The endpoint ID (string) for which to reverse the isolation. You can retrieve it from the xdr-get-endpoints command. | Required |
| suppress_disconnected_endpoint_error | Whether to suppress an error when trying to unisolate a disconnected endpoint. When sets to false, an error will be returned. Possible values are: true, false. Default is false. | Optional |
| interval_in_seconds | Interval in seconds between each poll. | Optional |
| timeout_in_seconds | Polling timeout in seconds. | Optional |
| action_id | For polling use. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.UnIsolation.endpoint_id | String | Isolates the specified endpoint. |
xdr-get-endpoints
Gets a list of endpoints, according to the passed filters. If there are no filters, all endpoints are returned. Filtering by multiple fields will be concatenated using AND condition (OR is not supported). Maximum result set size is 100. Offset is the zero-based number of endpoint from the start of the result set (start by counting from 0).
Required Permissions
Required Permissions For API call:
Endpoint Administrations –> View
Builtin Roles with this permission includes: “Privileged Responder”, “Viewer” and “Instance Admin”.
Base Command
xdr-get-endpoints
Input
| Argument Name | Description | Required |
|---|---|---|
| status | A comma-separated list of endpoints statuses to filter. Valid values are: connected, disconnected, lost, uninstalled, windows, linux, macos, android, isolated, unisolated. | Optional |
| endpoint_id_list | A comma-separated list of endpoint IDs. | Optional |
| dist_name | A comma-separated list of distribution package names or installation package names. Example: dist_name1,dist_name2. |
Optional |
| ip_list | A comma-separated list of private IP addresses. Example: Example: 10.1.1.1,192.168.1.1. |
Optional |
| public_ip_list | A comma-separated list of public IP addresses that correlate to the last IPv4 address from which the Cortex XDR agent connected (know as Last Origin IP).Example: 8.8.8.8,1.1.1.1. |
Optional |
| group_name | The group name to which the agent belongs. Example: group_name1,group_name2. |
Optional |
| platform | The endpoint platform. Valid values are: “windows”, “linux”, “macos”, or “android”. . Possible values are: windows, linux, macos, android. | Optional |
| alias_name | A comma-separated list of alias names. Examples: alias_name1,alias_name2. |
Optional |
| isolate | Specifies whether the endpoint was isolated or unisolated. Possible values are: isolated, unisolated. | Optional |
| hostname | Hostname Example: hostname1,hostname2. |
Optional |
| first_seen_gte | All the agents that were first seen after {first_seen_gte}. Supported values: 1579039377301 (time in milliseconds) “3 days” (relative date) “2019-10-21T23:45:00” (date). |
Optional |
| first_seen_lte | All the agents that were first seen before {first_seen_lte}. Supported values: 1579039377301 (time in milliseconds) “3 days” (relative date) “2019-10-21T23:45:00” (date). |
Optional |
| last_seen_gte | All the agents that were last seen before {last_seen_gte}. Supported values: 1579039377301 (time in milliseconds) “3 days” (relative date) “2019-10-21T23:45:00” (date). |
Optional |
| last_seen_lte | All the agents that were last seen before {last_seen_lte}. Supported values: 1579039377301 (time in milliseconds) “3 days” (relative date) “2019-10-21T23:45:00” (date). |
Optional |
| page | Page number (for pagination). The default is 0 (the first page). Default is 0. | Optional |
| limit | Maximum number of endpoints to return per page. The default and maximum is 30. Default is 30. | Optional |
| sort_by | Specifies whether to sort endpoints by the first time or last time they were seen. Can be “first_seen” or “last_seen”. Possible values are: first_seen, last_seen. | Optional |
| sort_order | The order by which to sort results. Can be “asc” (ascending) or “desc” ( descending). Default set to asc. Possible values are: asc, desc. Default is asc. | Optional |
| username | The usernames to query for, accepts a single user, or comma-separated list of usernames. | Optional |
| all_results | Whether to return all endpoints. If true, will override the ‘limit’ and ‘page’ arguments. Possible values are: false, true. Default is false. | Optional |
| use_hr_timestamps | Whether to return timestamp values in human-readable format as opposed to Unix epoch timestamp format. Possible values are: false, true. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.Endpoint.endpoint_id | String | The endpoint ID. |
| PaloAltoNetworksXDR.Endpoint.endpoint_name | String | The endpoint name. |
| PaloAltoNetworksXDR.Endpoint.endpoint_type | String | The endpoint type. |
| PaloAltoNetworksXDR.Endpoint.endpoint_status | String | The status of the endpoint. |
| PaloAltoNetworksXDR.Endpoint.os_type | String | The endpoint OS type. |
| PaloAltoNetworksXDR.Endpoint.ip | Unknown | A list of IP addresses. |
| PaloAltoNetworksXDR.Endpoint.users | Unknown | A list of users. |
| PaloAltoNetworksXDR.Endpoint.domain | String | The endpoint domain. |
| PaloAltoNetworksXDR.Endpoint.alias | String | The endpoint’s aliases. |
| PaloAltoNetworksXDR.Endpoint.first_seen | Unknown | First seen date/time in Epoch (milliseconds). |
| PaloAltoNetworksXDR.Endpoint.last_seen | Date | Last seen date/time in Epoch (milliseconds). |
| PaloAltoNetworksXDR.Endpoint.content_version | String | Content version. |
| PaloAltoNetworksXDR.Endpoint.installation_package | String | Installation package. |
| PaloAltoNetworksXDR.Endpoint.active_directory | String | Active directory. |
| PaloAltoNetworksXDR.Endpoint.install_date | Date | Install date in Epoch (milliseconds). |
| PaloAltoNetworksXDR.Endpoint.endpoint_version | String | Endpoint version. |
| PaloAltoNetworksXDR.Endpoint.is_isolated | String | Whether the endpoint is isolated. |
| PaloAltoNetworksXDR.Endpoint.group_name | String | The name of the group to which the endpoint belongs. |
| PaloAltoNetworksXDR.Endpoint.count | String | Number of endpoints returned. |
| Endpoint.Hostname | String | The hostname that is mapped to this endpoint. |
| Endpoint.ID | String | The unique ID within the tool retrieving the endpoint. |
| Endpoint.IPAddress | String | The IP address of the endpoint. |
| Endpoint.Domain | String | The domain of the endpoint. |
| Endpoint.OS | String | The endpoint’s operation system. |
| Account.Username | String | The username in the relevant system. |
| Account.Domain | String | The domain of the account. |
| Endpoint.Status | String | The endpoint’s status. |
| Endpoint.IsIsolated | String | The endpoint’s isolation status. |
| Endpoint.MACAddress | String | The endpoint’s MAC address. |
| Endpoint.Vendor | String | The integration name of the endpoint vendor. |
Command Example
!xdr-get-endpoints isolate="unisolated" first_seen_gte="3 month" page="0" limit="30" sort_order="asc"
Context Example
{
"Endpoint": [
{
"Domain": "WORKGROUP",
"Hostname": "aaaaa.compute.internal",
"ID": "ea303670c76e4ad09600c8b346f7c804",
"IPAddress": [
"172.31.11.11"
],
"OS": "Windows",
"Status" : "Online",
"IsIsolated" : "No",
"Vendor": "Cortex XDR - IR"
},
{
"Domain": "WORKGROUP",
"Hostname": "EC2AMAZ-P7PPOI4",
"ID": "f8a2f58846b542579c12090652e79f3d",
"IPAddress": [
"2.2.2.2"
],
"OS": "Windows",
"Status" : "Online",
"IsIsolated" : "No",
"Vendor": "Cortex XDR - IR"
}
],
"PaloAltoNetworksXDR.Endpoint": [
{
"domain": "",
"users": [
"ec2-user"
],
"endpoint_name": "aaaaa.compute.internal",
"ip": [
"172.31.11.11"
],
"install_date": 1575795969644,
"endpoint_version": "7.0.0.1915",
"group_name": null,
"installation_package": "linux",
"alias": "",
"active_directory": null,
"endpoint_status": "CONNECTED",
"os_type": "AGENT_OS_LINUX",
"endpoint_id": "ea303670c76e4ad09600c8b346f7c804",
"content_version": "111-17757",
"first_seen": 1575795969644,
"endpoint_type": "AGENT_TYPE_SERVER",
"is_isolated": "AGENT_UNISOLATED",
"last_seen": 1579290023629
},
{
"domain": "WORKGROUP",
"users": [
"Administrator"
],
"endpoint_name": "EC2AMAZ-P7PPOI4",
"ip": [
"2.2.2.2"
],
"install_date": 1575796381739,
"endpoint_version": "7.0.0.27797",
"group_name": null,
"installation_package": "Windows Server 2016",
"alias": "",
"active_directory": null,
"endpoint_status": "CONNECTED",
"os_type": "AGENT_OS_WINDOWS",
"endpoint_id": "f8a2f58846b542579c12090652e79f3d",
"content_version": "111-17757",
"first_seen": 1575796381739,
"endpoint_type": "AGENT_TYPE_SERVER",
"is_isolated": "AGENT_UNISOLATED",
"last_seen": 1579289957412
}
]
}
Human Readable Output
Endpoints
active_directory alias content_version domain endpoint_id endpoint_name endpoint_status endpoint_type endpoint_version first_seen group_name install_date installation_package ip is_isolated last_seen os_type users 111-17757 ea303670c76e4ad09600c8b346f7c804 aaaaa.compute.internal CONNECTED AGENT_TYPE_SERVER 7.0.0.1915 1575795969644 1575795969644 linux 172.31.11.11 AGENT_UNISOLATED 1579290023629 AGENT_OS_LINUX ec2-user 111-17757 WORKGROUP f8a2f58846b542579c12090652e79f3d EC2AMAZ-P7PPOI4 CONNECTED AGENT_TYPE_SERVER 7.0.0.27797 1575796381739 1575796381739 Windows Server 2016 2.2.2.2 AGENT_UNISOLATED 1579289957412 AGENT_OS_WINDOWS Administrator
xdr-get-distribution-versions
Gets a list of all the agent versions to use for creating a distribution list.
Required Permissions
Required Permissions For API call:
Endpoint Installations –> View
Builtin Roles with this permission includes: “Viewer” and “Instance Admin”.
Base Command
xdr-get-distribution-versions
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.DistributionVersions.windows | Unknown | A list of Windows agent versions. |
| PaloAltoNetworksXDR.DistributionVersions.linux | Unknown | A list of Linux agent versions. |
| PaloAltoNetworksXDR.DistributionVersions.macos | Unknown | A list of Mac agent versions. |
Command Example
##### Context Example
{
“PaloAltoNetworksXDR.DistributionVersions”: {
“windows”: [
“5.0.8.29673”,
“5.0.9.30963”,
“6.1.4.28751”,
“7.0.0.28644”
],
“macos”: [
“6.1.4.1681”,
“7.0.0.1914”
],
“linux”: [
“6.1.4.1680”,
“7.0.0.1916”
]
}
}
##### Human Readable Output
>### windows
>|versions|
>|---|
>| 5.0.8.29673 |
>| 5.0.9.30963 |
>| 6.1.4.28751 |
>| 7.0.0.28644 |
>
>
>### linux
>|versions|
>|---|
>| 6.1.4.1680 |
>| 7.0.0.1916 |
>
>
>### macos
>|versions|
>|---|
>| 6.1.4.1681 |
>| 7.0.0.1914 |
### xdr-create-distribution
***
Creates an installation package. This is an asynchronous call that returns the distribution ID. This does not mean that the creation succeeded. To confirm that the package has been created, check the status of the distribution by running the Get Distribution Status API.
##### Required Permissions
Required Permissions For API call:
`Endpoint Installations` --> `View/ Edit`
Builtin Roles with this permission includes: "Instance Admin".
#### Base Command
`xdr-create-distribution`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| name | A string representing the name of the installation package. | Required |
| platform | String, valid values are:<br/>• windows <br/>• linux<br/>• macos <br/>• android. Possible values are: windows, linux, macos, android. | Required |
| package_type | A string representing the type of package to create.<br/>standalone - An installation for a new agent<br/>upgrade - An upgrade of an agent from ESM. Possible values are: standalone, upgrade. | Required |
| agent_version | agent_version returned from xdr-get-distribution-versions. Not required for Android platform. | Required |
| description | Information about the package. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.Distribution.id | String | The installation package ID. |
| PaloAltoNetworksXDR.Distribution.name | String | The name of the installation package. |
| PaloAltoNetworksXDR.Distribution.platform | String | The installation OS. |
| PaloAltoNetworksXDR.Distribution.agent_version | String | Agent version. |
| PaloAltoNetworksXDR.Distribution.description | String | Information about the package. |
##### Command Example
```!xdr-create-distribution agent_version=6.1.4.1680 name="dist_1" package_type=standalone platform=linux description="some description"```
##### Context Example
{
“PaloAltoNetworksXDR.Distribution”: {
“description”: “some description”,
“package_type”: “standalone”,
“platform”: “linux”,
“agent_version”: “6.1.4.1680”,
“id”: “43aede7f846846fa92b50149663fbb25”,
“name”: “dist_1”
}
}
##### Human Readable Output
Distribution 43aede7f846846fa92b50149663fbb25 created successfully
### xdr-get-distribution-url
***
Gets the distribution URL for downloading the installation package.
##### Required Permissions
Required Permissions For API call:
`Endpoint Installations` --> `View`
Builtin Roles with this permission includes: "Viewer" and "Instance Admin".
#### Base Command
`xdr-get-distribution-url`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| distribution_id | The ID of the installation package.<br/>Copy the distribution_id from the "id" field on Endpoints > Agent Installation page. | Required |
| package_type | The installation package type. Valid<br/>values are:<br/>• upgrade<br/>• sh - For Linux<br/>• rpm - For Linux<br/>• deb - For Linux<br/>• pkg - For Mac<br/>• x86 - For Windows<br/>• x64 - For Windows. Possible values are: upgrade, sh, rpm, deb, pkg, x86, x64. | Required |
| download_package | Supported only for package_type x64 or x86. Whether to download the installation package file. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.Distribution.id | String | Distribution ID. |
| PaloAltoNetworksXDR.Distribution.url | String | URL for downloading the installation package. |
##### Command Example
```!xdr-get-distribution-url distribution_id=2c74c11b63074653aa01d575a82bf52a package_type=sh```
### xdr-get-create-distribution-status
***
Gets the status of the installation package.
##### Required Permissions
Required Permissions For API call:
`Endpoint Installations` --> `View`
Builtin Roles with this permission includes: "Viewer" and "Instance Admin".
#### Base Command
`xdr-get-create-distribution-status`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| distribution_ids | A comma-separated list of distribution IDs to get the status for. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.Distribution.id | String | Distribution ID. |
| PaloAltoNetworksXDR.Distribution.status | String | The status of installation package. |
##### Command Example
```!xdr-get-create-distribution-status distribution_ids=2c74c11b63074653aa01d575a82bf52a```
### xdr-get-audit-management-logs
***
Gets management logs. You can filter by multiple fields, which will be concatenated using the AND condition (OR is not supported). Maximum result set size is 100. Offset is the zero-based number of management logs from the start of the result set (start by counting from 0).
##### Required Permissions
Required Permissions For API call:
`Auditing` --> `View`
Builtin Roles with this permission includes: "Viewer" and "Instance Admin".
##### Context Example
{
“PaloAltoNetworksXDR.Distribution”: [
{
“status”: “Completed”,
“id”: “2c74c11b63074653aa01d575a82bf52a”
}
]
}
##### Human Readable Output
>### Distribution Status
>|id|status|
>|---|---|
>| 2c74c11b63074653aa01d575a82bf52a | Completed |
#### Base Command
`xdr-get-audit-management-logs`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| email | User’s email address. | Optional |
| type | The audit log type. Possible values are: LIVE_TERMINAL, RULES, AUTH, RESPONSE, INCIDENT_MANAGEMENT, ENDPOINT_MANAGEMENT, ALERT_WHITELIST, PUBLIC_API, DISTRIBUTIONS, STARRED_INCIDENTS, POLICY_PROFILES, DEVICE_CONTROL_PROFILE, HOST_FIREWALL_PROFILE, POLICY_RULES, PROTECTION_POLICY, DEVICE_CONTROL_TEMP_EXCEPTIONS, DEVICE_CONTROL_GLOBAL_EXCEPTIONS, GLOBAL_EXCEPTIONS, MSSP, REPORTING, DASHBOARD, BROKER_VM. | Optional |
| sub_type | The audit log subtype. | Optional |
| result | Result type. Possible values are: SUCCESS, FAIL, PARTIAL. | Optional |
| timestamp_gte | Return logs for which the timestamp is after 'log_time_after'.<br/>Supported values:<br/>1579039377301 (time in milliseconds)<br/>"3 days" (relative date)<br/>"2019-10-21T23:45:00" (date). | Optional |
| timestamp_lte | Return logs for which the timestamp is before the 'log_time_after'.<br/>Supported values:<br/>1579039377301 (time in milliseconds)<br/>"3 days" (relative date)<br/>"2019-10-21T23:45:00" (date). | Optional |
| page | Page number (for pagination). The default is 0 (the first page). Default is 0. | Optional |
| limit | Maximum number of audit logs to return per page. The default and maximum is 30. Default is 30. | Optional |
| sort_by | Specifies the field by which to sort the results. By default the sort is defined as creation-time and DESC. Can be "type", "sub_type", "result", or "timestamp". Possible values are: type, sub_type, result, timestamp. | Optional |
| sort_order | The sort order. Can be "asc" (ascending) or "desc" (descending). Default set to "desc". Possible values are: asc, desc. Default is desc. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.AuditManagementLogs.AUDIT_ID | Number | Audit log ID. |
| PaloAltoNetworksXDR.AuditManagementLogs.AUDIT_OWNER_NAME | String | Audit owner name. |
| PaloAltoNetworksXDR.AuditManagementLogs.AUDIT_OWNER_EMAIL | String | Audit owner email address. |
| PaloAltoNetworksXDR.AuditManagementLogs.AUDIT_ASSET_JSON | String | Asset JSON. |
| PaloAltoNetworksXDR.AuditManagementLogs.AUDIT_ASSET_NAMES | String | Audit asset names. |
| PaloAltoNetworksXDR.AuditManagementLogs.AUDIT_HOSTNAME | String | Host name. |
| PaloAltoNetworksXDR.AuditManagementLogs.AUDIT_RESULT | String | Audit result. |
| PaloAltoNetworksXDR.AuditManagementLogs.AUDIT_REASON | String | Audit reason. |
| PaloAltoNetworksXDR.AuditManagementLogs.AUDIT_DESCRIPTION | String | Description of the audit. |
| PaloAltoNetworksXDR.AuditManagementLogs.AUDIT_ENTITY | String | Audit entity (e.g., AUTH, DISTRIBUTIONS). |
| PaloAltoNetworksXDR.AuditManagementLogs.AUDIT_ENTITY_SUBTYPE | String | Entity subtype (e.g., Login, Create). |
| PaloAltoNetworksXDR.AuditManagementLogs.AUDIT_CASE_ID | Number | Audit case ID. |
| PaloAltoNetworksXDR.AuditManagementLogs.AUDIT_INSERT_TIME | Date | Log's insert time. |
### xdr-get-audit-agent-reports
***
Gets agent event reports. You can filter by multiple fields, which will be concatenated using the AND condition (OR is not supported). Maximum result set size is 100. Offset is the zero-based number of reports from the start of the result set (start by counting from 0).
##### Required Permissions
Required Permissions For API call:
`Auditing` --> `View`
Builtin Roles with this permission includes: "Viewer" and "Instance Admin".
#### Base Command
`xdr-get-audit-agent-reports`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| endpoint_ids | A comma-separated list of endpoint IDs. | Optional |
| endpoint_names | A comma-separated list of endpoint names. | Optional |
| type | The report type. Can be "Installation", "Policy", "Action", "Agent Service", "Agent Modules", or "Agent Status". Possible values are: Installation, Policy, Action, Agent Service, Agent Modules, Agent Status. | Optional |
| sub_type | The report subtype. Possible values are: Install, Uninstall, Upgrade, Local Configuration, Content Update, Policy Update, Process Exception, Hash Exception, Scan, File Retrieval, File Scan, Terminate Process, Isolate, Cancel Isolation, Payload Execution, Quarantine, Restore, Stop, Start, Module Initialization, Local Analysis Model, Local Analysis Feature Extraction, Fully Protected, OS Incompatible, Software Incompatible, Kernel Driver Initialization, Kernel Extension Initialization, Proxy Communication, Quota Exceeded, Minimal Content, Reboot Required, Missing Disc Access. | Optional |
| result | The result type. Can be "Success" or "Fail". If not passed, returns all event reports. Possible values are: Success, Fail. | Optional |
| timestamp_gte | Return logs that their timestamp is greater than 'log_time_after'.<br/>Supported values:<br/>1579039377301 (time in milliseconds)<br/>"3 days" (relative date)<br/>"2019-10-21T23:45:00" (date). | Optional |
| timestamp_lte | Return logs for which the timestamp is before the 'timestamp_lte'.<br/><br/>Supported values:<br/>1579039377301 (time in milliseconds)<br/>"3 days" (relative date)<br/>"2019-10-21T23:45:00" (date). | Optional |
| page | Page number (for pagination). The default is 0 (the first page). Default is 0. | Optional |
| limit | The maximum number of reports to return. Default and maximum is 30. Default is 30. | Optional |
| sort_by | The field by which to sort results. Can be "type", "category", "trapsversion", "timestamp", or "domain"). Possible values are: type, category, trapsversion, timestamp, domain. | Optional |
| sort_order | The sort order. Can be "asc" (ascending) or "desc" (descending). Default is "asc". Possible values are: asc, desc. Default is asc. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.AuditAgentReports.ENDPOINTID | String | Endpoint ID. |
| PaloAltoNetworksXDR.AuditAgentReports.ENDPOINTNAME | String | Endpoint name. |
| PaloAltoNetworksXDR.AuditAgentReports.DOMAIN | String | Agent domain. |
| PaloAltoNetworksXDR.AuditAgentReports.TRAPSVERSION | String | Traps version. |
| PaloAltoNetworksXDR.AuditAgentReports.RECEIVEDTIME | Date | Received time in Epoch time. |
| PaloAltoNetworksXDR.AuditAgentReports.TIMESTAMP | Date | Timestamp in Epoch time. |
| PaloAltoNetworksXDR.AuditAgentReports.CATEGORY | String | Report category (e.g., Audit). |
| PaloAltoNetworksXDR.AuditAgentReports.TYPE | String | Report type (e.g., Action, Policy). |
| PaloAltoNetworksXDR.AuditAgentReports.SUBTYPE | String | Report subtype (e.g., Fully Protected,Policy Update,Cancel Isolation\). |
| PaloAltoNetworksXDR.AuditAgentReports.RESULT | String | Report result. |
| PaloAltoNetworksXDR.AuditAgentReports.REASON | String | Report reason. |
| PaloAltoNetworksXDR.AuditAgentReports.DESCRIPTION | String | Agent report description. |
| Endpoint.ID | String | The unique ID within the tool retrieving the endpoint. |
| Endpoint.Hostname | String | The hostname that is mapped to this endpoint. |
| Endpoint.Domain | String | The domain of the endpoint. |
### xdr-blocklist-files
***
Block lists requested files which have not already been block listed or added to allow lists.
##### Required Permissions
Required Permissions For API call:
`Action Center` --> `View/ Edit`
`Action Center` --> `Allow List/Block List`
Builtin Roles with this permission includes: "Responder", "Privileged Responder" and "Instance Admin".
#### Base Command
`xdr-blocklist-files`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| incident_id | Links the response action to the triggered incident. | Optional |
| hash_list | String that represents a list of hashed files you want to block list. Must be a valid SHA256 hash. | Required |
| comment | String that represents additional information regarding the action. | Optional |
| detailed_response | Choose either regular response or detailed response. Default value = false, regular response. Possible values are: true, false. Default is false. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.blocklist.added_hashes | Number | Number of file hashes added to block list. |
| PaloAltoNetworksXDR.blocklist.excluded_hashes | Number | Number of file hashes excluded from block list. |
### xdr-allowlist-files
***
Adds requested files to allow list if they are not already on block list or allow list.
##### Required Permissions
Required Permissions For API call:
`Action Center` --> `View/ Edit`
`Action Center` --> `Allow List/Block List`
Builtin Roles with this permission includes: "Responder", "Privileged Responder" and "Instance Admin".
#### Base Command
`xdr-allowlist-files`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| incident_id | Links the response action to the triggered incident. | Optional |
| hash_list | String that represents a list of hashed files you want to add to allow lists. Must be a valid SHA256 hash. | Required |
| comment | String that represents additional information regarding the action. | Optional |
| detailed_response | Choose either regular response or detailed response. Default value = false, regular response. Possible values are: true, false. Default is false. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.allowlist.added_hashes | Number | Number of added file hashes to allowlist. |
| PaloAltoNetworksXDR.allowlist.excluded_hashes | Number | Number of excluded file hashes from allowlist. |
### xdr-file-quarantine
***
Quarantines a file on selected endpoints. You can select up to 1000 endpoints.
##### Required Permissions
Required Permissions For API call:
`Action Center` --> `View/ Edit`
`Action Center` --> `Quarantine`
Builtin Roles with this permission includes: "Responder", "Privileged Responder" and "Instance Admin".
#### Base Command
`xdr-file-quarantine`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| incident_id | Allows linking the response action to the incident that triggered it. | Optional |
| endpoint_id_list | List of endpoint IDs. | Required |
| file_path | String that represents the path of the file you want to quarantine. | Required |
| file_hash | String that represents the file's hash. Must be a valid SHA256 hash. | Required |
| interval_in_seconds | Interval in seconds between each poll. | Optional |
| timeout_in_seconds | Polling timeout in seconds. | Optional |
| action_id | The action IDs for polling use. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.bucket | String | The bucket in which the error occurred. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_name | String | The name of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_path | String | The path of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_size | Number | The size of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.missing_files | Unknown | The missing files that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorData | String | The error reason data. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminated_by | String | The instance ID which terminated the action and caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorDescription | String | The error reason description. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminate_result | Unknown | The error reason terminate result. |
### xdr-get-quarantine-status
***
Retrieves the quarantine status for a selected file.
##### Required Permissions
Required Permissions For API call:
`Action Center` --> `View/ Edit`
`Action Center` --> `Quarantine`
Builtin Roles with this permission includes: "Responder", "Privileged Responder" and "Instance Admin".
#### Base Command
`xdr-get-quarantine-status`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| endpoint_id | String the represents the endpoint ID. | Required |
| file_hash | String that represents the file hash. Must be a valid SHA256 hash. | Required |
| file_path | String that represents the file path. | Required |
#### Context Output
There is no context output for this command.
### xdr-file-restore
***
Restores a quarantined file on requested endpoints.
##### Required Permissions
Required Permissions For API call:
`Action Center` --> `View/ Edit`
`Action Center` --> `Quarantine`
Builtin Roles with this permission includes: "Responder", "Privileged Responder" and "Instance Admin".
#### Base Command
`xdr-file-restore`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| incident_id | Allows linking the response action to the incident that triggered it. | Optional |
| file_hash | The hash code of the file. Must be a valid SHA256 hash. | Required |
| endpoint_id | String that represents the endpoint ID. If you do not enter a specific endpoint ID, the request will run restore on all endpoints that relate to the quarantined file you defined. | Optional |
| interval_in_seconds | Interval in seconds between each poll. | Optional |
| timeout_in_seconds | Polling timeout in seconds. | Optional |
| action_id | The action IDs for polling use. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.bucket | String | The bucket in which the error occurred. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_name | String | The name of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_path | String | The path of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_size | Number | The size of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.missing_files | Unknown | The missing files that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorData | String | The error reason data. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminated_by | String | The instance ID which terminated the action and caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorDescription | String | The error reason description. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminate_result | Unknown | The error reason terminate result. |
### xdr-endpoint-scan-execute
***
Runs a scan on a selected endpoint. To scan all endpoints, run this command with argument all=true. Note: scanning all the endpoints may cause performance issues and latency.
##### Required Permissions
Required Permissions For API call:
`Action Center` --> `View`
`Endpoint Administrations` --> `View/ Edit`
`Endpoint Administrations` --> `Endpoint Scan`
Builtin Roles with this permission includes: "Privileged Responder" and "Instance Admin".
#### Base Command
`xdr-endpoint-scan-execute`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| incident_id | Allows linking the response action to the incident that triggered it. | Optional |
| endpoint_id_list | List of endpoint IDs. | Optional |
| dist_name | Name of the distribution list. | Optional |
| gte_first_seen | Greater than or equal to first seen timestamp in milliseconds. | Optional |
| gte_last_seen | Greater than or equal to last seen timestamp in milliseconds. | Optional |
| lte_first_seen | Less than or equal to first seen timestamp in milliseconds. | Optional |
| lte_last_seen | Less than or equal to last seen timestamp in milliseconds. | Optional |
| ip_list | List of IP addresses. | Optional |
| group_name | Name of the endpoint group. | Optional |
| platform | Type of operating system. Possible values are: windows, linux, macos, android. | Optional |
| alias | Endpoint alias name. | Optional |
| isolate | Whether an endpoint has been isolated. Possible values are: isolated, unisolated. | Optional |
| hostname | Name of the host. | Optional |
| all | Whether to scan all of the endpoints. Scanning all of the endpoints may cause performance issues and latency. Possible values are: true, false. Default is false. | Optional |
| action_id | The action IDs for polling use. | Optional |
| interval_in_seconds | Interval in seconds between each poll. | Optional |
| timeout_in_seconds | Polling timeout in seconds. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.endpointScan.actionId | Number | The action ID of the scan request. |
| PaloAltoNetworksXDR.endpointScan.aborted | Boolean | Was the scan aborted? |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.bucket | String | The bucket in which the error occurred. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_name | String | The name of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_path | String | The path of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_size | Number | The size of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.missing_files | Unknown | The missing files that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorData | String | The error reason data. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminated_by | String | The instance ID which terminated the action and caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorDescription | String | The error reason description. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminate_result | Unknown | The error reason terminate result. |
### xdr-endpoint-scan-abort
***
Cancels the scan of selected endpoints. A scan can only be aborted if the selected endpoints are Pending or In Progress. To scan all endpoints, run the command with the argument all=true. Note that scanning all of the endpoints may cause performance issues and latency.
##### Required Permissions
Required Permissions For API call:
`Endpoint Administrations` --> `View/ Edit`
`Endpoint Administrations` --> `Endpoint Scan`
Builtin Roles with this permission includes: "Privileged Responder" and "Instance Admin".
#### Base Command
`xdr-endpoint-scan-abort`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| incident_id | Allows linking the response action to the incident that triggered it. | Optional |
| endpoint_id_list | List of endpoint IDs. | Optional |
| dist_name | Name of the distribution list. | Optional |
| gte_first_seen | GTE first seen timestamp in milliseconds. | Optional |
| gte_last_seen | GTE last seen timestamp in milliseconds. | Optional |
| lte_first_seen | LTE first seen timestamp in milliseconds. | Optional |
| lte_last_seen | LTE last seen timestamp in milliseconds. | Optional |
| ip_list | List of IP addresses. | Optional |
| group_name | Name of the endpoint group. | Optional |
| platform | Type of operating system. Possible values are: windows, linux, macos, android. | Optional |
| alias | Endpoint alias name. | Optional |
| isolate | Whether an endpoint has been isolated. Can be "isolated" or "unisolated". Possible values are: isolated, unisolated. | Optional |
| hostname | Name of the host. | Optional |
| all | Whether to scan all of the endpoints. Note: scanning all of the endpoints may cause performance issues and latency. Possible values are: true, false. Default is false. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.endpointScan.actionId | Unknown | The action ID of the abort scan request. |
| PaloAltoNetworksXDR.endpointScan.aborted | Boolean | Was the scan aborted? |
### get-mapping-fields
***
Gets mapping fields from remote incident. Note: This method will not update the current incident, it's here for debugging purposes.
#### Base Command
`get-mapping-fields`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
#### Context Output
There is no context output for this command.
### get-remote-data
***
Gets remote data from a remote incident. Note: This method will not update the current incident, it's here for debugging purposes.
#### Base Command
`get-remote-data`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| id | The remote incident ID. | Required |
| lastUpdate | UTC timestamp in seconds. The incident is only updated if it was modified after the last update time. Default is 0. | Optional |
#### Context Output
There is no context output for this command.
### get-modified-remote-data
***
Gets the list of incidents that were modified since the last update. Note: This method is here for debugging purposes. get-modified-remote-data is used as part of a Mirroring feature, which is available since version 6.1.
#### Base Command
`get-modified-remote-data`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| lastUpdate | Date string representing the local time.The incident is only returned if it was modified after the last update time. | Optional |
#### Context Output
There is no context output for this command.
### xdr-get-policy
***
Gets the policy name for a specific endpoint.
##### Required Permissions
Required Permissions For API call:
`Endpoint Prevention Policies` --> `View`
Builtin Roles with this permission includes: "Privileged Investigator", "Privileged Responder", "Viewer", and "Instance Admin".
#### Base Command
`xdr-get-policy`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| endpoint_id | The endpoint ID. Can be retrieved by running the xdr-get-endpoints command. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.Policy | string | The policy allocated with the endpoint. |
| PaloAltoNetworksXDR.Policy.policy_name | string | Name of the policy allocated with the endpoint. |
| PaloAltoNetworksXDR.Policy.endpoint_id | string | Endpoint ID. |
### xdr-get-scripts
***
Gets a list of scripts available in the scripts library.
##### Required Permissions
Required Permissions For API call:
`Agent Scripts library` --> `View`
`Endpoint Administrations` --> `View/ Edit`
`Endpoint Administrations` --> `Endpoint Scan`
Builtin Roles with this permission includes: "Privileged Responder", "Viewer" and "Instance Admin".
#### Base Command
`xdr-get-scripts`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| script_name | A comma-separated list of the script names. | Optional |
| description | A comma-separated list of the script descriptions. | Optional |
| created_by | A comma-separated list of the users who created the script. | Optional |
| limit | The maximum number of scripts returned to the War Room. | Optional |
| offset | (Int) Offset in the data set. | Optional |
| windows_supported | Whether the script can be executed on a Windows operating system. Possible values are: true, false. | Optional |
| linux_supported | Whether the script can be executed on a Linux operating system. Possible values are: true, false. | Optional |
| macos_supported | Whether the script can be executed on a Mac operating system. Possible values are: true, false. | Optional |
| is_high_risk | Whether the script has a high-risk outcome. Possible values are: true, false. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.Scripts | Unknown | The scripts command results. |
| PaloAltoNetworksXDR.Scripts.script_id | Unknown | Script ID. |
| PaloAltoNetworksXDR.Scripts.name | string | Name of the script. |
| PaloAltoNetworksXDR.Scripts.description | string | Description of the script. |
| PaloAltoNetworksXDR.Scripts.modification_date | Unknown | Timestamp of when the script was last modified. |
| PaloAltoNetworksXDR.Scripts.created_by | string | Name of the user who created the script. |
| PaloAltoNetworksXDR.Scripts.windows_supported | boolean | Whether the script can be executed on a Windows operating system. |
| PaloAltoNetworksXDR.Scripts.linux_supported | boolean | Whether the script can be executed on a Linux operating system. |
| PaloAltoNetworksXDR.Scripts.macos_supported | boolean | Whether the script can be executed on Mac operating system. |
| PaloAltoNetworksXDR.Scripts.is_high_risk | boolean | Whether the script has a high-risk outcome. |
| PaloAltoNetworksXDR.Scripts.script_uid | string | Globally Unique Identifier of the script, used to identify the script when executing. |
### xdr-delete-endpoints
***
Deletes selected endpoints in the Cortex XDR app. You can delete up to 1000 endpoints.
##### Required Permissions
Required Permissions For API call:
`Endpoint Administrations` --> `View/ Edit`
Builtin Roles with this permission includes: "Privileged Responder" and "Instance Admin".
#### Base Command
`xdr-delete-endpoints`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| endpoint_ids | A comma-separated list of endpoint IDs. You can retrieve the endpoint IDs from the xdr-get-endpoints command. | Required |
#### Context Output
There is no context output for this command.
### xdr-get-endpoint-device-control-violations
***
Gets a list of device control violations filtered by selected fields. You can retrieve up to 100 violations.
##### Required Permissions
Required Permissions For API call:
`Device Control` --> `View`
Builtin Roles with this permission includes: "Privileged Investigator", "Privileged Responder", "Viewer", and "Instance Admin".
#### Base Command
`xdr-get-endpoint-device-control-violations`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| endpoint_ids | A comma-separated list of endpoint IDs. You can retrieve the endpoint IDs from the xdr-get-endpoints command. | Optional |
| type | Type of violation. Possible values are: "cd-rom", "disk drive", "floppy disk", and "portable device". Possible values are: cd-rom, disk drive, floppy disk, portable device. | Optional |
| timestamp_gte | Timestamp of the violation. Violations that are greater than or equal to this timestamp will be returned. Values can be in either ISO date format, relative time, or epoch timestamp. For example: "2019-10-21T23:45:00" (ISO date format), "3 days ago" (relative time) 1579039377301 (epoch time). | Optional |
| timestamp_lte | Timestamp of the violation. Violations that are less than or equal to this timestamp will be returned. Values can be in either ISO date format, relative time, or epoch timestamp. For example: "2019-10-21T23:45:00" (ISO date format), "3 days ago" (relative time) 1579039377301 (epoch time). | Optional |
| ip_list | A comma-separated list of IP addresses. | Optional |
| vendor | Name of the vendor. | Optional |
| vendor_id | Vendor ID. | Optional |
| product | Name of the product. | Optional |
| product_id | Product ID. | Optional |
| serial | Serial number. | Optional |
| hostname | Hostname. | Optional |
| violation_id_list | A comma-separated list of violation IDs. | Optional |
| username | Username. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.EndpointViolations | Unknown | Endpoint violations command results. |
| PaloAltoNetworksXDR.EndpointViolations.violations | Unknown | A list of violations. |
| PaloAltoNetworksXDR.EndpointViolations.violations.os_type | string | Type of the operating system. |
| PaloAltoNetworksXDR.EndpointViolations.violations.hostname | string | Host name of the violation. |
| PaloAltoNetworksXDR.EndpointViolations.violations.username | string | Username of the violation. |
| PaloAltoNetworksXDR.EndpointViolations.violations.ip | string | IP address of the violation. |
| PaloAltoNetworksXDR.EndpointViolations.violations.timestamp | number | Timestamp of the violation. |
| PaloAltoNetworksXDR.EndpointViolations.violations.violation_id | number | Violation ID. |
| PaloAltoNetworksXDR.EndpointViolations.violations.type | string | Type of violation. |
| PaloAltoNetworksXDR.EndpointViolations.violations.vendor_id | string | Vendor ID of the violation. |
| PaloAltoNetworksXDR.EndpointViolations.violations.vendor | string | Name of the vendor of the violation. |
| PaloAltoNetworksXDR.EndpointViolations.violations.product_id | string | Product ID of the violation. |
| PaloAltoNetworksXDR.EndpointViolations.violations.product | string | Name of the product of the violation. |
| PaloAltoNetworksXDR.EndpointViolations.violations.serial | string | Serial number of the violation. |
| PaloAltoNetworksXDR.EndpointViolations.violations.endpoint_id | string | Endpoint ID of the violation. |
### xdr-file-retrieve
***
Retrieves files from selected endpoints. You can retrieve up to 20 files, from no more than 10 endpoints. At least one endpoint ID and one file path are necessary in order to run the command. After running this command, you can use the xdr-action-status-get command with returned action_id, to check the action status.
##### Required Permissions
Required Permissions For API call:
`Action Center` --> `View/ Edit`
`Action Center` --> `File Retrieval`
Builtin Roles with this permission includes: "Privileged Responder" and "Instance Admin".
#### Base Command
`xdr-file-retrieve`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| incident_id | Allows to link the response action to the incident that triggered it. | Optional |
| endpoint_ids | A comma-separated list of endpoint IDs. | Required |
| windows_file_paths | A comma-separated list of file paths on the Windows platform. | Optional |
| linux_file_paths | A comma-separated list of file paths on the Linux platform. | Optional |
| mac_file_paths | A comma-separated list of file paths on the Mac platform. | Optional |
| generic_file_path | A comma-separated list of file paths in any platform. Can be used instead of the mac/windows/linux file paths. The order of the files path list must be parallel to the endpoints list order, so the first file path in the list is related to the first endpoint and so on. | Optional |
| paths_separator | The delimiter used to separate multiple file paths. Set to a different character (for example, ";") when a file path contains a comma. Default is ,. | Optional |
| interval_in_seconds | Interval in seconds between each poll. | Optional |
| timeout_in_seconds | Polling timeout in seconds. | Optional |
| action_id | The action IDs for polling use. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.RetrievedFiles.action_id | string | ID of the action to retrieve files from selected endpoints. |
| PaloAltoNetworksXDR.RetrievedFiles.endpoint_id | string | Endpoint ID. Added only when the operation is successful. |
| PaloAltoNetworksXDR.RetrievedFiles.file_link | string | Link to the file. Added only when the operation is successful. |
| PaloAltoNetworksXDR.RetrievedFiles.status | string | The action status. Added only when the operation is unsuccessful. |
| PaloAltoNetworksXDR.RetrievedFiles.ErrorReasons.bucket | String | The bucket in which the error occurred. |
| PaloAltoNetworksXDR.RetrievedFiles.ErrorReasons.file_name | String | The name of the file that caused the error. |
| PaloAltoNetworksXDR.RetrievedFiles.ErrorReasons.file_path | String | The path of the file that caused the error. |
| PaloAltoNetworksXDR.RetrievedFiles.ErrorReasons.file_size | Number | The size of the file that caused the error. |
| PaloAltoNetworksXDR.RetrievedFiles.ErrorReasons.missing_files | Unknown | The missing files that caused the error. |
| PaloAltoNetworksXDR.RetrievedFiles.ErrorReasons.errorData | String | The error reason data. |
| PaloAltoNetworksXDR.RetrievedFiles.ErrorReasons.terminated_by | String | The instance ID which terminated the action and caused the error. |
| PaloAltoNetworksXDR.RetrievedFiles.ErrorReasons.errorDescription | String | The error reason description. |
| PaloAltoNetworksXDR.RetrievedFiles.ErrorReasons.terminate_result | Unknown | The error reason terminate result. |
### xdr-retrieve-file-details
***
View the file retrieved by the xdr-retrieve-files command according to the action ID. Before running this command, you can use the xdr-action-status-get command to check if this action completed successfully.
##### Required Permissions
Required Permissions For API call:
`Action Center` --> `View/ Edit`
`Action Center` --> `File Retrieval`
Builtin Roles with this permission includes: "Privileged Responder" and "Instance Admin".
#### Base Command
`xdr-retrieve-file-details`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| action_id | Action ID retrieved from the xdr-retrieve-files command. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| File | Unknown | The file details command results. |
| File.Name | String | The full file name \(including the file extension\). |
| File.EntryID | String | The ID for locating the file in the War Room. |
| File.Size | Number | The size of the file in bytes. |
| File.MD5 | String | The MD5 hash of the file. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.SHA512 | String | The SHA512 hash of the file. |
| File.Extension | String | The file extension. For example: "xls". |
| File.Type | String | The file type, as determined by libmagic \(same as displayed in file entries\). |
### xdr-get-script-metadata
***
Gets the full definition of a specific script in the scripts library.
##### Required Permissions
Required Permissions For API call:
`Agent Scripts library` --> `View`
Builtin Roles with this permission includes: "Privileged Responder", "Viewer" and "Instance Admin".
#### Base Command
`xdr-get-script-metadata`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| script_uid | Unique identifier of the script, returned by the xdr-get-scripts command. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.ScriptMetadata | Unknown | The script metadata command results. |
| PaloAltoNetworksXDR.ScriptMetadata.script_id | number | Script ID. |
| PaloAltoNetworksXDR.ScriptMetadata.name | string | Script name. |
| PaloAltoNetworksXDR.ScriptMetadata.description | string | Script description. |
| PaloAltoNetworksXDR.ScriptMetadata.modification_date | unknown | Timestamp of when the script was last modified. |
| PaloAltoNetworksXDR.ScriptMetadata.created_by | string | Name of the user who created the script. |
| PaloAltoNetworksXDR.ScriptMetadata.is_high_risk | boolean | Whether the script has a high-risk outcome. |
| PaloAltoNetworksXDR.ScriptMetadata.windows_supported | boolean | Whether the script can be executed on a Windows operating system. |
| PaloAltoNetworksXDR.ScriptMetadata.linux_supported | boolean | Whether the script can be executed on a Linux operating system. |
| PaloAltoNetworksXDR.ScriptMetadata.macos_supported | boolean | Whether the script can be executed on a Mac operating system. |
| PaloAltoNetworksXDR.ScriptMetadata.entry_point | string | Name of the entry point selected for the script. An empty string indicates the script defined as just run. |
| PaloAltoNetworksXDR.ScriptMetadata.script_input | string | Name and type for the specified entry point. |
| PaloAltoNetworksXDR.ScriptMetadata.script_output_type | string | Type of the output. |
| PaloAltoNetworksXDR.ScriptMetadata.script_output_dictionary_definitions | Unknown | If the script_output_type is a dictionary, an array with friendly name, name, and type for each output. |
### xdr-get-script-code
***
Gets the code of a specific script in the script library.
##### Required Permissions
Required Permissions For API call:
`Agent Scripts library` --> `View`
Builtin Roles with this permission includes: "Privileged Responder", "Viewer" and "Instance Admin".
#### Base Command
`xdr-get-script-code`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| script_uid | Unique identifier of the script, returned by the xdr-get-scripts command. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.ScriptCode | Unknown | The script code command results. |
| PaloAltoNetworksXDR.ScriptCode.code | string | The code of a specific script in the script library. |
| PaloAltoNetworksXDR.ScriptCode.script_uid | string | Unique identifier of the script. |
### xdr-action-status-get
***
Retrieves the status of the requested actions according to the action ID.
##### Required Permissions
Required Permissions For API call:
`Action Center` --> `View`
Builtin Roles with this permission includes: "Responder", "Privileged Investigator", "Privileged Responder", "Viewer", and "Instance Admin".
#### Base Command
`xdr-action-status-get`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| action_id | The action ID of the selected request. After performing an action, you will receive an action ID. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.GetActionStatus | Unknown | The action status command results. |
| PaloAltoNetworksXDR.GetActionStatus.endpoint_id | string | Endpoint ID. |
| PaloAltoNetworksXDR.GetActionStatus.status | string | The status of the specific endpoint ID. |
| PaloAltoNetworksXDR.GetActionStatus.action_id | number | The specified action ID. |
### xdr-run-script
***
Deprecated. Use the `xdr-script-run` command instead. Initiates a new endpoint script execution action using a script from the script library.
#### Base Command
`xdr-run-script`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| incident_id | Allows linking the response action to the incident that triggered it. | Optional |
| endpoint_ids | A comma-separated list of endpoint IDs. Can be retrieved by running the xdr-get-endpoints command. | Required |
| script_uid | Unique identifier of the script. Can be retrieved by running the xdr-get-scripts command. | Required |
| parameters | Dictionary containing the parameter name as key and its value for this execution as the value. For example, {"param1":"param1_value","param2":"param2_value"}. | Optional |
| timeout | The timeout in seconds for this execution. Default is 600. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.ScriptRun.action_id | Number | ID of the action initiated. |
| PaloAltoNetworksXDR.ScriptRun.endpoints_count | Number | Number of endpoints the action was initiated on. |
### xdr-snippet-code-script-execute
***
Initiates a new endpoint script execution action using the provided snippet code.
##### Required Permissions
Required Permissions For API call:
`Action Center` --> `View`
Builtin Roles with this permission includes: "Responder", "Privileged Investigator", "Privileged Responder", "Viewer", and "Instance Admin".
#### Base Command
`xdr-snippet-code-script-execute`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| incident_id | Allows linking the response action to the incident that triggered it. | Optional |
| endpoint_ids | A comma-separated list of endpoint IDs. Can be retrieved by running the xdr-get-endpoints command. | Required |
| snippet_code | Section of a script to initiate on an endpoint (e.g., print("7")). | Required |
| interval_in_seconds | Interval in seconds between each poll. | Optional |
| timeout_in_seconds | Polling timeout in seconds. | Optional |
| action_id | Action IDs for polling use. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.ScriptRun.action_id | Number | ID of the action initiated. |
| PaloAltoNetworksXDR.ScriptRun.endpoints_count | Number | Number of endpoints the action was initiated on. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.bucket | String | The bucket in which the error occurred. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_name | String | The name of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_path | String | The path of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_size | Number | The size of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.missing_files | Unknown | The missing files that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorData | String | The error reason data. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminated_by | String | The instance ID which terminated the action and caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorDescription | String | The error reason description. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminate_result | Unknown | The error reason terminate result. |
### xdr-get-script-execution-status
***
Retrieves the status of a script execution action.
##### Required Permissions
Required Permissions For API call:
`Agent Scripts library` --> `View`
Builtin Roles with this permission includes: "Privileged Responder", "Viewer" and "Instance Admin".
#### Base Command
`xdr-get-script-execution-status`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| action_id | Action IDs retrieved from the xdr-run-script command. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.ScriptStatus.general_status | String | General status of the action, considering the status of all the endpoints. |
| PaloAltoNetworksXDR.ScriptStatus.error_message | String | Error message regarding permissions for running APIs or the action doesn’t exist. |
| PaloAltoNetworksXDR.ScriptStatus.endpoints_timeout | Number | Number of endpoints in "timeout" status. |
| PaloAltoNetworksXDR.ScriptStatus.action_id | Number | ID of the action initiated. |
| PaloAltoNetworksXDR.ScriptStatus.endpoints_pending_abort | Number | Number of endpoints in "pending abort" status. |
| PaloAltoNetworksXDR.ScriptStatus.endpoints_pending | Number | Number of endpoints in "pending" status. |
| PaloAltoNetworksXDR.ScriptStatus.endpoints_in_progress | Number | Number of endpoints in "in progress" status. |
| PaloAltoNetworksXDR.ScriptStatus.endpoints_failed | Number | Number of endpoints in "failed" status. |
| PaloAltoNetworksXDR.ScriptStatus.endpoints_expired | Number | Number of endpoints in "expired" status. |
| PaloAltoNetworksXDR.ScriptStatus.endpoints_completed_successfully | Number | Number of endpoints in "completed successfully" status. |
| PaloAltoNetworksXDR.ScriptStatus.endpoints_canceled | Number | Number of endpoints in "canceled" status. |
| PaloAltoNetworksXDR.ScriptStatus.endpoints_aborted | Number | Number of endpoints in "aborted" status. |
### xdr-get-script-execution-results
***
Retrieve the results of a script execution action.
##### Required Permissions
Required Permissions For API call:
`Agent Scripts library` --> `View`
Builtin Roles with this permission includes: "Privileged Responder", "Viewer" and "Instance Admin".
#### Base Command
`xdr-get-script-execution-results`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| action_id | Action IDs retrieved from the xdr-run-script command. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.ScriptResult.action_id | Number | ID of the action initiated. |
| PaloAltoNetworksXDR.ScriptResult.results.retrieved_files | Number | Number of successfully retrieved files. |
| PaloAltoNetworksXDR.ScriptResult.results.endpoint_ip_address | String | Endpoint IP address. |
| PaloAltoNetworksXDR.ScriptResult.results.endpoint_name | String | Name of successfully retrieved files. |
| PaloAltoNetworksXDR.ScriptResult.results.failed_files | Number | Number of files failed to retrieve. |
| PaloAltoNetworksXDR.ScriptResult.results.endpoint_status | String | Endpoint status. |
| PaloAltoNetworksXDR.ScriptResult.results.domain | String | Domain to which the endpoint belongs. |
| PaloAltoNetworksXDR.ScriptResult.results.endpoint_id | String | Endpoint ID. |
| PaloAltoNetworksXDR.ScriptResult.results.execution_status | String | Execution status of this endpoint. |
| PaloAltoNetworksXDR.ScriptResult.results.return_value | String | Value returned by the script in case the type is not a dictionary. |
| PaloAltoNetworksXDR.ScriptResult.results.standard_output | String | The STDOUT and the STDERR logged by the script during the execution. |
| PaloAltoNetworksXDR.ScriptResult.results.retention_date | Date | Timestamp in which the retrieved files will be deleted from the server. |
### xdr-get-script-execution-result-files
***
Gets the files retrieved from a specific endpoint during a script execution.
##### Required Permissions
Required Permissions For API call:
`Agent Scripts library` --> `View`
Builtin Roles with this permission includes: "Privileged Responder", "Viewer" and "Instance Admin".
#### Base Command
`xdr-get-script-execution-result-files`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| action_id | Action ID retrieved from the xdr-run-script command. | Required |
| endpoint_id | Endpoint ID. Can be retrieved by running the xdr-get-endpoints command. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| File.Size | String | The size of the file. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.SHA512 | String | The SHA512 hash of the file. |
| File.Name | String | The name of the file. |
| File.SSDeep | String | The SSDeep hash of the file. |
| File.EntryID | String | EntryID of the file |
| File.Info | String | Information about the file. |
| File.Type | String | The file type. |
| File.MD5 | String | The MD5 hash of the file. |
| File.Extension | String | The extension of the file. |
### xdr-script-commands-execute
***
Initiates a new endpoint script execution of shell commands.
#### Base Command
`xdr-script-commands-execute`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| incident_id | Allows linking the response action to the incident that triggered it. | Optional |
| endpoint_ids | A comma-separated list of endpoint IDs. Can be retrieved by running the xdr-get-endpoints command. | Required |
| commands | A comma-separated list of shell commands to execute. Set the `is_raw_command` argument to `true` to prevent splitting by commas. (Useful when using `\|\|`, `&&`, `;` separators for controlling the flow of multiple commands). | Required |
| is_raw_command | Whether to pass the command as-is. When false, the command is split by commas and sent as a list of commands, that are run independently. | Optional |
| command_type | Type of shell command. Possible values are: powershell, native. | Optional |
| timeout | The timeout in seconds for this execution. Default is 600. | Optional |
| interval_in_seconds | Interval in seconds between each poll. | Optional |
| timeout_in_seconds | Polling timeout in seconds. | Optional |
| action_id | The action IDs for polling use. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.ScriptRun.action_id | Number | ID of the action initiated. |
| PaloAltoNetworksXDR.ScriptRun.endpoints_count | Number | Number of endpoints the action was initiated on. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.bucket | String | The bucket in which the error occurred. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_name | String | The name of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_path | String | The path of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_size | Number | The size of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.missing_files | Unknown | The missing files that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorData | String | The error reason data. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminated_by | String | The instance ID which terminated the action and caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorDescription | String | The error reason description. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminate_result | Unknown | The error reason terminate result. |
### xdr-file-delete-script-execute
***
Initiates a new endpoint script execution to delete the specified file.
#### Base Command
`xdr-file-delete-script-execute`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- |-----------------------------------------------------------------------------------------------------------------------| --- |
| incident_id | Allows linking the response action to the incident that triggered it. | Optional |
| endpoint_ids | A comma-separated list of endpoint IDs. Can be retrieved by running the xdr-get-endpoints command. | Required |
| file_path | A comma-separated list of paths of the files to delete. All of the given file paths will run on all of the endpoints. | Required |
| timeout | The timeout in seconds for this execution. Default is 600. | Optional |
| interval_in_seconds | Interval in seconds between each poll. | Optional |
| timeout_in_seconds | Polling timeout in seconds. | Optional |
| action_id | The action IDs for polling use. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.ScriptRun.action_id | Number | ID of the action initiated. |
| PaloAltoNetworksXDR.ScriptRun.endpoints_count | Number | Number of endpoints the action was initiated on. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.bucket | String | The bucket in which the error occurred. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_name | String | The name of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_path | String | The path of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_size | Number | The size of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.missing_files | Unknown | The missing files that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorData | String | The error reason data. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminated_by | String | The instance ID which terminated the action and caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorDescription | String | The error reason description. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminate_result | Unknown | The error reason terminate result. |
### xdr-file-exist-script-execute
***
Initiates a new endpoint script execution to check if the file exists.
#### Base Command
`xdr-file-exist-script-execute`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| incident_id | Allows linking the response action to the incident that triggered it. | Optional |
| endpoint_ids | A comma-separated list of endpoint IDs. Can be retrieved by running the xdr-get-endpoints command. | Required |
| file_path | A comma-separated list of paths of the files to check for existence. All of the given file paths will run on all of the endpoints. | Required |
| timeout | The timeout in seconds for this execution. Default is 600. | Optional |
| interval_in_seconds | Interval in seconds between each poll. | Optional |
| timeout_in_seconds | Polling timeout in seconds. | Optional |
| action_id | The action IDs for polling use. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.ScriptRun.action_id | Number | ID of the action initiated. |
| PaloAltoNetworksXDR.ScriptRun.endpoints_count | Number | Number of endpoints the action was initiated on. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.bucket | String | The bucket in which the error occurred. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_name | String | The name of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_path | String | The path of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_size | Number | The size of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.missing_files | Unknown | The missing files that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorData | String | The error reason data. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminated_by | String | The instance ID which terminated the action and caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorDescription | String | The error reason description. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminate_result | Unknown | The error reason terminate result. |
### xdr-kill-process-script-execute
***
Initiates a new endpoint script execution kill process.
#### Base Command
`xdr-kill-process-script-execute`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| incident_id | Allows to link the response action to the incident that triggered it. | Optional |
| endpoint_ids | A comma-separated list of endpoint IDs. Can be retrieved by running the xdr-get-endpoints command. | Required |
| process_name | Names of processes to kill. Will kill all of the given processes on all of the endpoints. | Required |
| timeout | The timeout in seconds for this execution. Default is 600. | Optional |
| interval_in_seconds | Interval in seconds between each poll. | Optional |
| timeout_in_seconds | Polling timeout in seconds. | Optional |
| action_id | The action IDs for polling use. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.ScriptRun.action_id | Number | ID of the action initiated. |
| PaloAltoNetworksXDR.ScriptRun.endpoints_count | Number | Number of endpoints the action was initiated on. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.bucket | String | The bucket in which the error occurred. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_name | String | The name of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_path | String | The path of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.file_size | Number | The size of the file that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.missing_files | Unknown | The missing files that caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorData | String | The error reason data. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminated_by | String | The instance ID which terminated the action and caused the error. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.errorDescription | String | The error reason description. |
| PaloAltoNetworksXDR.GetActionStatus.ErrorReasons.terminate_result | Unknown | The error reason terminate result. |
### endpoint
***
Returns information about an endpoint.
##### Required Permissions
Required Permissions For API call:
`Endpoint Administrations` --> `View`
Builtin Roles with this permission includes: "Privileged Responder", "Viewer" and "Instance Admin".
#### Base Command
`endpoint`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| id | The endpoint ID. | Optional |
| ip | The endpoint IP address. | Optional |
| hostname | The endpoint host name. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Endpoint.Hostname | String | The endpoint hostname. |
| Endpoint.OS | String | The endpoint operation system. |
| Endpoint.IPAddress | String | The endpoint IP address. |
| Endpoint.ID | String | The endpoint ID. |
| Endpoint.Status | String | The endpoint status. |
| Endpoint.IsIsolated | String | The endpoint isolation status. |
| Endpoint.MACAddress | String | The endpoint MAC address. |
| Endpoint.Vendor | String | The integration name of the endpoint vendor. |
### xdr-get-endpoints-by-status
***
Returns the number of the connected\disconnected endpoints.
##### Required Permissions
Required Permissions For API call:
`Endpoint Administrations` --> `View`
Builtin Roles with this permission includes: "Privileged Responder", "Viewer" and "Instance Admin".
#### Base Command
`xdr-get-endpoints-by-status`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| status | The status of the endpoint to filter. Possible values are: connected, disconnected, lost, uninstalled. | Required |
| last_seen_gte | All the agents that were last seen before {last_seen_gte}. Supported<br/> values: 1579039377301 (time in milliseconds) "3 days" (relative date) "2019-10-21T23:45:00"<br/> (date). | Optional |
| last_seen_lte | All the agents that were last seen before {last_seen_lte}. Supported<br/> values: 1579039377301 (time in milliseconds) "3 days" (relative date) "2019-10-21T23:45:00"<br/> (date). | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.EndpointsStatus.status | String | The endpoint status. |
| PaloAltoNetworksXDR.EndpointsStatus.count | Number | The number of endpoints with this status. |
### xdr-get-cloud-original-alerts (Deprecated)
***
This command is deprecated. Returns information about each alert ID.
##### Required Permissions
Required Permissions For API call:
`Alerts & Incidents` --> `View`
Builtin Roles with this permission includes: "Investigator", "Responder", "Privileged Investigator", "Privileged Responder", "Viewer", and "Instance Admin".
#### Base Command
`xdr-get-cloud-original-alerts`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| alert_ids | A comma-separated list of alert IDs. | Required |
| events_from_decider_format | Whether to return events_from_decider context output as a dictionary (the raw API response) or as a list (improved for playbook automation) - relevant only when filter_alert_fields is set to False. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.OriginalAlert.event._time | String | The timestamp of the occurrence of the event. |
| PaloAltoNetworksXDR.OriginalAlert.event.vendor | String | Vendor name. |
| PaloAltoNetworksXDR.OriginalAlert.event.event_timestamp | Number | Event timestamp. |
| PaloAltoNetworksXDR.OriginalAlert.event.event_type | Number | Event type \(static 500\). |
| PaloAltoNetworksXDR.OriginalAlert.event.cloud_provider | String | The cloud provider - GCP, AZURE, or AWS. |
| PaloAltoNetworksXDR.OriginalAlert.event.project | String | The project in which the event occurred. |
| PaloAltoNetworksXDR.OriginalAlert.event.cloud_provider_event_id | String | The ID given to the event by the cloud provider, if the ID exists. |
| PaloAltoNetworksXDR.OriginalAlert.event.cloud_correlation_id | String | The ID the cloud provider is using to aggregate events that are part of the same general event. |
| PaloAltoNetworksXDR.OriginalAlert.event.operation_name_orig | String | The name of the operation that occurred, as supplied by the cloud provider. |
| PaloAltoNetworksXDR.OriginalAlert.event.operation_name | String | The normalized name of the operation performed by the event. |
| PaloAltoNetworksXDR.OriginalAlert.event.identity_orig | String | Contains the original identity related fields as provided by the cloud provider. |
| PaloAltoNetworksXDR.OriginalAlert.event.identity_name | String | The name of the identity that initiated the action. |
| PaloAltoNetworksXDR.OriginalAlert.event.identity_uuid | String | Same as identity_name but also contains the UUID of the identity if it exists. |
| PaloAltoNetworksXDR.OriginalAlert.event.identity_type | String | An enum representing the type of the identity. |
| PaloAltoNetworksXDR.OriginalAlert.event.identity_sub_type | String | An enum representing the sub-type of the identity, respective to its identity_type. |
| PaloAltoNetworksXDR.OriginalAlert.event.identity_invoked_by_name | String | The name of the identity that invoked the action as it appears in the log. |
| PaloAltoNetworksXDR.OriginalAlert.event.identity_invoked_by_uuid | String | The UUID of the identity that invoked the action as it appears in the log. |
| PaloAltoNetworksXDR.OriginalAlert.event.identity_invoked_by_type | String | An enum that represents the type of identity event that invoked the action. |
| PaloAltoNetworksXDR.OriginalAlert.event.identity_invoked_by_sub_type | String | An enum that represents the respective sub_type of the type of identity \(identity_type\) that has invoked the action. |
| PaloAltoNetworksXDR.OriginalAlert.event.operation_status | String | Status of whether the operation has succeed or failed, if provided. |
| PaloAltoNetworksXDR.OriginalAlert.event.operation_status_orig | String | The operation status code as it appears in the log, including lookup from code number to code name. |
| PaloAltoNetworksXDR.OriginalAlert.event.operation_status_orig_code | String | The operation status code as it appears in the log. |
| PaloAltoNetworksXDR.OriginalAlert.event.operation_status_reason_provided | String | Description of the error, if the log record indicates an error and the cloud provider supplied the reason. |
| PaloAltoNetworksXDR.OriginalAlert.event.resource_type | String | The normalized type of the service that emitted the log row. |
| PaloAltoNetworksXDR.OriginalAlert.event.resource_type_orig | String | The type of the service that omitted the log as provided by the cloud provider. |
| PaloAltoNetworksXDR.OriginalAlert.event.resource_sub_type | String | The sub-type respective to the resource_type field, normalized across all cloud providers. |
| PaloAltoNetworksXDR.OriginalAlert.event.resource_sub_type_orig | String | The sub-type of the service that emitted this log row as provided by the cloud provider. |
| PaloAltoNetworksXDR.OriginalAlert.event.region | String | The cloud region of the resource that emitted the log. |
| PaloAltoNetworksXDR.OriginalAlert.event.zone | String | The availability zone of the resource that emitted the log. |
| PaloAltoNetworksXDR.OriginalAlert.event.referenced_resource | String | The cloud resource referenced in the audit log. |
| PaloAltoNetworksXDR.OriginalAlert.event.referenced_resource_name | String | Same as referenced_resource but provides only the substring that represents the resource name instead of the full asset ID. |
| PaloAltoNetworksXDR.OriginalAlert.event.referenced_resources_count | Number | The number of extracted resources referenced in this audit log. |
| PaloAltoNetworksXDR.OriginalAlert.event.user_agent | String | The user agent provided in the call to the API of the cloud provider. |
| PaloAltoNetworksXDR.OriginalAlert.event.caller_ip | String | The IP of the caller that performed the action in the log. |
| PaloAltoNetworksXDR.OriginalAlert.event.caller_ip_geolocation | String | The geolocation associated with the caller_ip's value. |
| PaloAltoNetworksXDR.OriginalAlert.event.caller_ip_asn | Number | The ASN of the caller_ip's value. |
| PaloAltoNetworksXDR.OriginalAlert.event.caller_project | String | The project of the caller entity. |
| PaloAltoNetworksXDR.OriginalAlert.event.raw_log | Unknown | The raw log that is being normalized. |
| PaloAltoNetworksXDR.OriginalAlert.event.log_name | String | The name of the log that contains the log row. |
| PaloAltoNetworksXDR.OriginalAlert.event.caller_ip_asn_org | String | The organization associated with the ASN of the caller_ip's value. |
| PaloAltoNetworksXDR.OriginalAlert.event.event_base_id | String | Event base ID. |
| PaloAltoNetworksXDR.OriginalAlert.event.ingestion_time | String | Ingestion time. |
### xdr-remove-allowlist-files
***
Removes requested files from allow list.
##### Required Permissions
Required Permissions For API call:
`Action Center` --> `View/ Edit`
`Action Center` --> `Allow List/Block List`
Builtin Roles with this permission includes: "Responder", "Privileged Responder" and "Instance Admin".
#### Base Command
`xdr-remove-allowlist-files`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| incident_id | Links the response action to the incident that triggered it. | Optional |
| hash_list | String that represents a list of hashed files you want to add to allow list. Must be a valid SHA256 hash. | Required |
| comment | String that represents additional information regarding the action. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.allowlist.removed_hashes | Number | Removed file hash |
### xdr-remove-blocklist-files
***
Removes requested files from block list.
##### Required Permissions
Required Permissions For API call:
`Action Center` --> `View/ Edit`
`Action Center` --> `Allow List/Block List`
Builtin Roles with this permission includes: "Responder", "Privileged Responder" and "Instance Admin".
#### Base Command
`xdr-remove-blocklist-files`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| incident_id | Links the response action to the incident that triggered it. | Optional |
| hash_list | String that represents a list of hashed files you want to add to allow list. Must be a valid SHA256 hash. | Required |
| comment | String that represents additional information regarding the action. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.blocklist.removed_hashes | Number | Removed fileHash from blocklist |
There is no context output for this command.
### xdr-get-alerts (Deprecated)
***
This command is deprecated, please use xdr-issue-list instead. Returns a list of alerts and their metadata, which you can filter by built-in arguments or use the custom_filter to input a JSON filter object.
Multiple filter arguments will be concatenated using the AND operator, while arguments that support a comma-separated list of values will use an OR operator between each value.
##### Required Permissions
Required Permissions For API call:
`Alerts & Incidents` --> `View`
Builtin Roles with this permission includes: "Investigator", "Responder", "Privileged Investigator", "Privileged Responder", "Viewer", and "Instance Admin".
#### Base Command
`xdr-get-alerts`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| alert_id | The unique ID of the alert. | Optional |
| severity | The severity of the alert. Possible values are: low, medium, high. | Optional |
| custom_filter | a custom filter, when using this argument, other filter arguments are not relevant. example: <br/>`{<br/> "OR": [<br/> {<br/> "SEARCH_FIELD": "actor_process_command_line",<br/> "SEARCH_TYPE": "EQ",<br/> "SEARCH_VALUE": "path_to_file"<br/> }<br/> ]<br/> }`. | Optional |
| Identity_type | Account type. Possible values are: ANONYMOUS, APPLICATION, COMPUTE, FEDERATED_IDENTITY, SERVICE, SERVICE_ACCOUNT, TEMPORARY_CREDENTIALS, TOKEN, UNKNOWN, USER. | Optional |
| agent_id | A unique identifier per agent. | Optional |
| action_external_hostname | The host name to connect to. In case of a proxy connection, this value will differ from action_remote_ip. | Optional |
| rule_id | A string identifying the user rule. | Optional |
| rule_name | The name of the user rule. | Optional |
| alert_name | The alert name. | Optional |
| alert_source | The alert source. | Optional |
| time_frame | Supports relative times or “custom” time option. If you choose the "custom" option, you should use start_time and end_time arguments. Possible values are: 60 minutes, 3 hours, 12 hours, 24 hours, 2 days, 7 days, 14 days, 30 days, custom. | Optional |
| user_name | The name assigned to the user_id during agent runtime. | Optional |
| actor_process_image_name | The file name of the binary file. | Optional |
| causality_actor_process_image_command_line | CGO CMD. | Optional |
| actor_process_image_command_line | Trimmed to 128 unicode chars during event serialization.<br/>Full value reported as part of the original process event. | Optional |
| action_process_image_command_line | The command line of the process created. | Optional |
| actor_process_image_sha256 | SHA256 of the binary file. | Optional |
| causality_actor_process_image_sha256 | SHA256 of the binary file. | Optional |
| action_process_image_sha256 | SHA256 of the binary file. | Optional |
| action_file_image_sha256 | SHA256 of the file related to the event. | Optional |
| action_registry_name | The name of the registry. | Optional |
| action_registry_key_data | The key data of the registry. | Optional |
| host_ip | The host IP. | Optional |
| action_local_ip | The local IP address for the connection. | Optional |
| action_remote_ip | Remote IP address for the connection. | Optional |
| alert_action_status | Alert action status. Possible values are: detected, detected (allowed the session), detected (download), detected (forward), detected (post detected), detected (prompt allow), detected (raised an alert), detected (reported), detected (on write), detected (scanned), detected (sinkhole), detected (syncookie sent), detected (wildfire upload failure), detected (wildfire upload success), detected (wildfire upload skip), detected (xdr managed threat hunting), prevented (block), prevented (blocked), prevented (block-override), prevented (blocked the url), prevented (blocked the ip), prevented (continue), prevented (denied the session), prevented (dropped all packets), prevented (dropped the session), prevented (dropped the session and sent a tcp reset), prevented (dropped the packet), prevented (override), prevented (override-lockout), prevented (post detected), prevented (prompt block), prevented (random-drop), prevented (silently dropped the session with an icmp unreachable message to the host or application), prevented (terminated the session and sent a tcp reset to both sides of the connection), prevented (terminated the session and sent a tcp reset to the client), prevented (terminated the session and sent a tcp reset to the server), prevented (on write). | Optional |
| action_local_port | The local IP address for the connection. | Optional |
| action_remote_port | The remote port for the connection. | Optional |
| dst_action_external_hostname | The hostname we connect to. In case of a proxy connection, this value will differ from action_remote_ip. | Optional |
| sort_field | The field by which we sort the results. Default is source_insert_ts. | Optional |
| sort_order | The order in which we sort the results. Possible values are: DESC, ASC. | Optional |
| offset | The first page from which we bring the alerts. Default is 0. | Optional |
| limit | The last page from which we bring the alerts. Default is 50. | Optional |
| start_time | Relevant when "time_frame" argument is "custom". Supports Epoch timestamp and simplified extended ISO format (YYYY-MM-DDThh:mm:ss). | Optional |
| end_time | Relevant when "time_frame" argument is "custom". Supports Epoch timestamp and simplified extended ISO format (YYYY-MM-DDThh:mm:ss). | Optional |
| starred | Whether the alert is starred or not. Possible values are: true, false. | Optional |
| mitre_technique_id_and_name | The MITRE attack technique. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PaloAltoNetworksXDR.Alert.internal_id | String | The unique ID of the alert. |
| PaloAltoNetworksXDR.Alert.source_insert_ts | Number | The detection timestamp |
| PaloAltoNetworksXDR.Alert.alert_name | String | The name of the alert. |
| PaloAltoNetworksXDR.Alert.severity | String | The severity of the alert. |
| PaloAltoNetworksXDR.Alert.alert_category | String | The category of the alert. |
| PaloAltoNetworksXDR.Alert.alert_action_status | String | The alert action. Possible values.
DETECTED: detected
DETECTED_0: detected \(allowed the session\)
DOWNLOAD: detected \(download\)
DETECTED_19: detected \(forward\)
POST_DETECTED: detected \(post detected\)
PROMPT_ALLOW: detected \(prompt allow\)
DETECTED_4: detected \(raised an alert\)
REPORTED: detected \(reported\)
REPORTED_TRIGGER_4: detected \(on write\)
SCANNED: detected \(scanned\)
DETECTED_23: detected \(sinkhole\)
DETECTED_18: detected \(syncookie sent\)
DETECTED_21: detected \(wildfire upload failure\)
DETECTED_20: detected \(wildfire upload success\)
DETECTED_22: detected \(wildfire upload skip\)
DETECTED_MTH: detected \(xdr managed threat hunting\)
BLOCKED_25: prevented \(block\)
BLOCKED: prevented \(blocked\)
BLOCKED_14: prevented \(block-override\)
BLOCKED_5: prevented \(blocked the url\)
BLOCKED_6: prevented \(blocked the ip\)
BLOCKED_13: prevented \(continue\)
BLOCKED_1: prevented \(denied the session\)
BLOCKED_8: prevented \(dropped all packets\)
BLOCKED_2: prevented \(dropped the session\)
BLOCKED_3: prevented \(dropped the session and sent a tcp reset\)
BLOCKED_7: prevented \(dropped the packet\)
BLOCKED_16: prevented \(override\)
BLOCKED_15: prevented \(override-lockout\)
BLOCKED_26: prevented \(post detected\)
PROMPT_BLOCK: prevented \(prompt block\)
BLOCKED_17: prevented \(random-drop\)
BLOCKED_24: prevented \(silently dropped the session with an icmp unreachable message to the host or application\)
BLOCKED_9: prevented \(terminated the session and sent a tcp reset to both sides of the connection\)
BLOCKED_10: prevented \(terminated the session and sent a tcp reset to the client\)
BLOCKED_11: prevented \(terminated the session and sent a tcp reset to the server\)
BLOCKED_TRIGGER_4: prevented \(on write\)
|
| PaloAltoNetworksXDR.Alert.alert_action_status_readable | String | The alert action. |
| PaloAltoNetworksXDR.Alert.alert_name | String | The alert name. |
| PaloAltoNetworksXDR.Alert.alert_description | String | The alert description. |
| PaloAltoNetworksXDR.Alert.agent_ip_addresses | String | The host IP. |
| PaloAltoNetworksXDR.Alert.agent_hostname | String | The host name. |
| PaloAltoNetworksXDR.Alert.mitre_tactic_id_and_name | String | The MITRE attack tactic. |
| PaloAltoNetworksXDR.Alert.mitre_technique_id_and_name | String | The MITRE attack technique. |
| PaloAltoNetworksXDR.Alert.starred | Boolean | Whether the alert is starred or not. |
#### Command example
```!xdr-get-alerts severity="high" alert_action_status="detected (reported)" sort_field="source_insert_ts" offset="0" limit="1"```
#### Context Example
```json
{
"PaloAltoNetworksXDR": {
"Alert": {
"action_country": [
"UNKNOWN"
],
"action_external_hostname": null,
"action_file_macro_sha256": null,
"action_file_md5": null,
"action_file_name": null,
"action_file_path": null,
"action_file_sha256": null,
"action_local_ip": null,
"action_local_ip_v6": null,
"action_local_port": null,
"action_process_causality_id": null,
"action_process_image_command_line": null,
"action_process_image_md5": [
"ddcd2be64212b10c3cf84496a879b098"
],
"action_process_image_name": null,
"action_process_image_path": [
"C:\Users\administrator\Downloads\svchost.exe"
],
"action_process_image_sha256": null,
"action_process_instance_id": null,
"action_process_os_pid": [
5172
],
"action_process_signature_status": [
"SIGNATURE_UNAVAILABLE"
],
"action_process_signature_vendor": null,
"action_process_user_sid": null,
"action_registry_data": null,
"action_registry_full_key": null,
"action_registry_key_name": null,
"action_registry_value_name": null,
"action_remote_ip": null,
"action_remote_ip_v6": null,
"action_remote_port": null,
"activity_first_seen_at": null,
"activity_last_seen_at": null,
"actor_causality_id": null,
"actor_effective_user_sid": null,
"actor_effective_username": [
"env1.local\administrator"
],
"actor_process_causality_id": [
"AdhDcc/XHpAAABQ0AAAAAA=="
],
"actor_process_command_line": [
"\"C:\Users\administrator\Downloads\svchost.exe\" "
],
"actor_process_execution_time": [
1648560911622
],
"actor_process_image_md5": [
"ddcd2be64212b10c3cf84496a879b098"
],
"actor_process_image_name": [
"svchost.exe"
],
"actor_process_image_path": [
"C:\Users\administrator\Downloads\svchost.exe"
],
"actor_process_image_sha256": [
"b013074d220d71877112b61e16927abbbb98ad29aa40609aca1b936332fbe4b7"
],
"actor_process_instance_id": [
"AdhDcc/XHpAAABQ0AAAAAA=="
],
"actor_process_os_pid": [
5172
],
"actor_process_signature_status": [
"SIGNATURE_UNSIGNED"
],
"actor_process_signature_vendor": null,
"actor_thread_thread_id": [
2468
],
"agent_data_collection_status": true,
"agent_device_domain": "env1.local",
"agent_fqdn": "DC1ENV1APC02.env1.local",
"agent_host_boot_time": [
0
],
"agent_hostname": "DC1ENV1APC02",
"agent_id": "63f88a9e797440ccac742a6adc926fb2",
"agent_install_type": "STANDARD",
"agent_ip_addresses": [
"10.111.230.11"
],
"agent_ip_addresses_v6": null,
"agent_is_vdi": null,
"agent_os_sub_type": "10.0.10240",
"agent_os_type": "AGENT_OS_WINDOWS",
"agent_version": "7.6.1.46600",
"alert_action_status": "REPORTED",
"alert_action_status_readable": "detected (reported)",
"alert_category": "Malware",
"alert_description": "Behavioral threat detected (rule: bioc.masquerade_svchost)",
"alert_description_raw": "Behavioral threat detected (rule: bioc.masquerade_svchost)",
"alert_is_fp": false,
"alert_name": "Behavioral Threat",
"alert_source": "TRAPS",
"alert_sub_type": null,
"alert_type": "Unclassified",
"association_strength": [
50
],
"attack_techniques": null,
"attempt_counter": 0,
"audit_ids": null,
"bioc_category_enum_key": null,
"bioc_indicator": null,
"caller_ip": null,
"case_id": 48,
"causality_actor_causality_id": [
"AdhDcc/XHpAAABQ0AAAAAA=="
],
"causality_actor_process_command_line": [
"\"C:\Users\administrator\Downloads\svchost.exe\" "
],
"causality_actor_process_execution_time": [
1648560911622
],
"causality_actor_process_image_md5": null,
"causality_actor_process_image_name": [
"svchost.exe"
],
"causality_actor_process_image_path": [
"C:\Users\administrator\Downloads\svchost.exe"
],
"causality_actor_process_image_sha256": [
"b013074d220d71877112b61e16927abbbb98ad29aa40609aca1b936332fbe4b7"
],
"causality_actor_process_instance_id": [
"AdhDcc/XHpAAABQ0AAAAAA=="
],
"causality_actor_process_os_pid": [
5172
],
"causality_actor_process_signature_status": [
"SIGNATURE_UNSIGNED"
],
"causality_actor_process_signature_vendor": null,
"cloud_provider": null,
"cluster_name": null,
"container_id": null,
"contains_featured_host": [
"NO"
],
"contains_featured_ip": [
"NO"
],
"contains_featured_user": [
"NO"
],
"deduplicate_tokens": null,
"detection_modules": null,
"dns_query_name": null,
"drilldown_max_ts": null,
"drilldown_min_ts": null,
"drilldown_query": null,
"dss_country": null,
"dss_department": null,
"dss_groups": null,
"dss_job_title": null,
"dst_action_country": null,
"dst_action_external_hostname": null,
"dst_action_external_port": null,
"dst_actor_process_image_name": null,
"dst_actor_process_os_pid": null,
"dst_agent_hostname": null,
"dst_agent_id": null,
"dst_agent_os_type": [
"NO_HOST"
],
"dst_association_strength": null,
"dst_causality_actor_process_execution_time": null,
"dst_os_actor_process_image_name": null,
"dst_os_actor_process_os_pid": null,
"dynamic_fields": {
"action_country": [
"UNKNOWN"
],
"action_process_signature_status": [
"SIGNATURE_UNAVAILABLE"
],
"activated": "0001-01-01T00:00:00Z",
"activatingingUserId": "",
"actor_effective_username": [
"env1.local\administrator"
],
"actor_process_command_line": [
"\"C:\Users\administrator\Downloads\svchost.exe\" "
],
"actor_process_image_md5": [
"ddcd2be64212b10c3cf84496a879b098"
],
"actor_process_image_name": [
"svchost.exe"
],
"actor_process_image_path": [
"C:\Users\administrator\Downloads\svchost.exe"
],
"actor_process_image_sha256": [
"b013074d220d71877112b61e16927abbbb98ad29aa40609aca1b936332fbe4b7"
],
"actor_process_os_pid": [
5172
],
"actor_process_signature_status": [
"SIGNATURE_UNSIGNED"
],
"actor_thread_thread_id": [
2468
],
"agent_device_domain": "env1.local",
"agent_fqdn": "DC1ENV1APC02.env1.local",
"agent_hostname": "DC1ENV1APC02",
"agent_id": "63f88a9e797440ccac742a6adc926fb2",
"agent_ip_addresses": [
"10.111.230.11"
],
"agent_os_sub_type": "10.0.10240",
"agent_os_type": "AGENT_OS_WINDOWS",
"alert_action_status": "REPORTED",
"alert_category": "Malware",
"alert_description": "Behavioral threat detected (rule: bioc.masquerade_svchost)",
"alert_name": "Behavioral Threat",
"alert_source": "TRAPS",
"alert_type": "Unclassified",
"attachment": null,
"category": "",
"causality_actor_causality_id": [
"AdhDcc/XHpAAABQ0AAAAAA=="
],
"causality_actor_process_command_line": [
"\"C:\Users\administrator\Downloads\svchost.exe\" "
],
"causality_actor_process_image_name": [
"svchost.exe"
],
"causality_actor_process_image_path": [
"C:\Users\administrator\Downloads\svchost.exe"
],
"causality_actor_process_image_sha256": [
"b013074d220d71877112b61e16927abbbb98ad29aa40609aca1b936332fbe4b7"
],
"causality_actor_process_signature_status": [
"SIGNATURE_UNSIGNED"
],
"closeReason": "",
"closed": "0001-01-01T00:00:00Z",
"closingUserId": "",
"contains_featured_host": [
"NO"
],
"contains_featured_ip": [
"NO"
],
"contains_featured_user": [
"NO"
],
"dbotCurrentDirtyFields": null,
"dbotDirtyFields": null,
"dbotMirrorDirection": "",
"dbotMirrorId": "",
"dbotMirrorInstance": "",
"dbotMirrorLastSync": "0001-01-01T00:00:00Z",
"dbotMirrorTags": null,
"droppedCount": 0,
"dueDate": "0001-01-01T00:00:00Z",
"event_type": [
1
],
"feedBased": false,
"fw_is_phishing": [
"NOT_AVAILABLE"
],
"internal_id": 6887,
"investigationId": "6887",
"isDebug": false,
"is_whitelisted": false,
"labels": null,
"lastJobRunTime": "0001-01-01T00:00:00Z",
"lastOpen": "0001-01-01T00:00:00Z",
"linkedCount": 0,
"linkedIncidents": null,
"mac": "00:50:56:89:8b:8e",
"mitre_tactic_id_and_name": [
"TA0005 - Defense Evasion",
"TA0002 - Execution"
],
"mitre_technique_id_and_name": [
"T1036.005 - Masquerading: Match Legitimate Name or Location"
],
"module_id": [
"Behavioral Threat Protection"
],
"notifyTime": "2022-09-21T06:45:17.746532863Z",
"occurred": "0001-01-01T00:00:00Z",
"openDuration": 0,
"os_actor_process_signature_status": [
"SIGNATURE_UNAVAILABLE"
],
"os_actor_thread_thread_id": [
2468
],
"phase": "",
"playbookId": "T1036 - Masquerading",
"reason": "",
"reminder": "0001-01-01T00:00:00Z",
"resolution_comment": "",
"resolution_status": "STATUS_020_UNDER_INVESTIGATION",
"runStatus": "error",
"severity": "SEV_040_HIGH",
"sla": 0,
"sourceInstance": "",
"source_insert_ts": 1648560949000,
"starred": false
},
"end_match_attempt_ts": null,
"event_id": null,
"event_sub_type": null,
"event_timestamp": [
1648560949290
],
"event_type": [
1
],
"events_length": 1,
"external_id": "d4c2983dfab74741b087dce1bbffd8d5",
"family_tags": null,
"filter_rule_id": null,
"forensics_artifact_type": null,
"from_dml": null,
"fw_app_category": null,
"fw_app_id": null,
"fw_app_subcategory": null,
"fw_app_technology": null,
"fw_device_name": null,
"fw_email_recipient": null,
"fw_email_sender": null,
"fw_email_subject": null,
"fw_interface_from": null,
"fw_interface_to": null,
"fw_is_phishing": [
"NOT_AVAILABLE"
],
"fw_misc": null,
"fw_rule": null,
"fw_rule_id": null,
"fw_serial_number": null,
"fw_url_domain": null,
"fw_vsys": null,
"fw_xff": null,
"identity_invoked_by_type": null,
"identity_name": null,
"identity_sub_type": null,
"identity_type": null,
"image_name": null,
"internal_id": "6887",
"iot_pivot_url": null,
"is_disintegrated": null,
"is_pcap": false,
"is_whitelisted": false,
"is_xsoar_alert": false,
"last_modified_ts": 1663742717853,
"local_insert_ts": 1648560958017,
"mac": "00:50:56:89:8b:8e",
"matching_service_rule_id": null,
"matching_status": "MATCHED",
"mitre_tactic_id_and_name": [
"TA0005 - Defense Evasion",
"TA0002 - Execution"
],
"mitre_technique_id_and_name": [
"T1036.005 - Masquerading: Match Legitimate Name or Location"
],
"module_id": [
"Behavioral Threat Protection"
],
"module_name": [
"COMPONENT_DSE"
],
"operation_name": null,
"original_severity": "SEV_040_HIGH",
"os_actor_causality_id": null,
"os_actor_effective_username": null,
"os_actor_process_causality_id": null,
"os_actor_process_command_line": null,
"os_actor_process_execution_time": null,
"os_actor_process_image_md5": null,
"os_actor_process_image_name": null,
"os_actor_process_image_path": null,
"os_actor_process_image_sha256": null,
"os_actor_process_instance_id": null,
"os_actor_process_os_pid": null,
"os_actor_process_signature_status": [
"SIGNATURE_UNAVAILABLE"
],
"os_actor_process_signature_vendor": null,
"os_actor_thread_thread_id": [
2468
],
"phone_number": null,
"pivot_url": null,
"playbook_suggestion_rule_id": null,
"policy_id": null,
"project": null,
"query_tables": null,
"referenced_resource": null,
"remote_cid": null,
"resolution_comment": "",
"resolution_status": "STATUS_020_UNDER_INVESTIGATION",
"resource_sub_type": null,
"resource_type": null,
"severity": "SEV_040_HIGH",
"source_insert_ts": 1648560949290,
"starred": false,
"story_id": null,
"suggested_playbook_id": null,
"tim_main_indicator": null,
"user_agent": null,
"xpanse_asset_id": null,
"xpanse_asset_name": null,
"xpanse_policy_id": null,
"xpanse_primary_asset_id": null,
"xpanse_service_id": null
}
}
}
Human Readable Output
Alerts
Action Alert ID Category Description Detection Timestamp Host IP Host Name Name Severity detected (reported) 6887 Malware Behavioral threat detected (rule: bioc.masquerade_svchost) 2022-03-29T13:35:49.000Z 10.111.230.11 DC1ENV1APC02 Behavioral Threat SEV_040_HIGH
xdr-get-contributing-event
Retrieves contributing events for a specific correlation alert.
Known limitation: the command is compatible only with correlation alerts, otherwise an error will be raised.
Required Permissions
Required Permissions For API call:
Alerts & Incidents –> View
Builtin Roles with this permission includes: “Investigator”, “Responder”, “Privileged Investigator”, “Privileged Responder”, “Viewer”, and “Instance Admin”.
Base Command
xdr-get-contributing-event
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_ids | The alert ID’s from where to retrieve the contributing events. | Required |
| limit | The maximum number of contributing events to retrieve. Default is 50. | Optional |
| page_number | The page number to retrieve. Minimum is 1. Default is 1. | Optional |
| page_size | The page size. Default is 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.ContributingEvent.alertID | String | The alert ID. |
| PaloAltoNetworksXDR.ContributingEvent.events | Unknown | Contributing events per alert. |
Command example
!xdr-get-contributing-event alert_ids=`[123456 , 123457]`
Context Example
{
"PaloAltoNetworksXDR": {
"ContributingEvent": [
{
"alertID": "123456",
"events": [
{
"Domain": "WIN10X64",
"Host_Name": "WIN10X64",
"Logon_Type": "7",
"Process_Name": "C:\\Windows\\System32\\svchost.exe",
"Raw_Message": "An account was successfully logged on.",
"Source_IP": "1.1.1.1",
"User_Name": "xsoar",
"111111": 15,
"222222": 165298280000,
"333333": "abcdef",
"444444": 1,
"555555": "ghijk",
"_is_cardable": true,
"_product": "XDR agent",
"_time": 165298280000,
"_vendor": "PANW",
"insert_timestamp": 165298280001
}
]
},
{
"alert_id": "123457",
"events": [
{
"Domain": "WIN10X64",
"Host_Name": "WIN10X64",
"Logon_Type": "7",
"Process_Name": "C:\\Windows\\System32\\svchost.exe",
"Raw_Message": "An account was successfully logged on",
"Source_IP": "1.1.1.1",
"User_Name": "xsoar",
"111111": 15,
"222222": 165298280000,
"333333": "abcdef",
"444444": 1,
"555555": "ghijk",
"_is_cardable": true,
"_product": "XDR agent",
"_time": 165298280000,
"_vendor": "PANW",
"insert_timestamp": 165298280001
}
]
}
]
}
}
Human Readable Output
Contributing events
Alert _ Id Events 123456 - Logon_Type: 7
User_Name: xsoar
Domain: WIN10X64
Source_IP: 1.1.1.1
Process_Name: C:\Windows\System32\svchost.exe
Host_Name: WIN10X64
Raw_Message: An account was successfully logged on. _time: 165298280000
555555: a1b2c3d4
222222: 165298280000
333333: abcdef
111111: 15
444444: 1
insert_timestamp: 165298280001
_vendor: PANW
_product: XDR agent
_is_cardable: true123457 - Logon_Type: 7
User_Name: xsoar
Domain: WIN10X64
Source_IP: 1.1.1.1
Process_Name: C:\Windows\System32\svchost.exe
Host_Name: WIN10X64
Raw_Message: An account was successfully logged on. _time: 165298280000
555555: ghijk
222222: 165298280000
333333: abcdef
111111: 15
444444: 1
insert_timestamp: 165298280001
_vendor: PANW
_product: XDR agent
_is_cardable: true
xdr-replace-featured-field
Replace the featured hosts\users\IP addresses\active directory groups listed in your environment.
Required Permissions
Required Permissions For API call:
Alerts & Incidents –> View/ Edit
Builtin Roles with this permission includes: “Investigator”, “Privileged Investigator”, “Privileged Responder” and “Instance Admin”.
Base Command
xdr-replace-featured-field
Input
| Argument Name | Description | Required |
|---|---|---|
| field_type | The field type to change. Possible values are: hosts, users, ip_addresses, ad_groups. | Required |
| values | The string value, which defines the new field. Maximum length is 256 characters. | Required |
| comments | The string value, which represents additional information regarding the featured alert field. | Optional |
| ad_type | The string value to replace an active directory group or organizational unit. Possible values are: group, ou. Default is group. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.FeaturedField.fieldType | String | The field type that changed. |
| PaloAltoNetworksXDR.FeaturedField.fields | String | String value that defines the new field. |
Command example
!xdr-replace-featured-field field_type=ip_addresses values=`["1.1.1.1"]` comments=`new ip address`
Context Example
{
"PaloAltoNetworksXDR": {
"FeaturedField": {
"fieldType": "ip_addresses",
"fields": [
{
"comment": "new ip address",
"value": "1.1.1.1"
}
]
}
}
}
Human Readable Output
Replaced featured: ip_addresses
Comment Value new ip address 1.1.1.1
xdr-list-users
Retrieve a list of the current users in the environment.
Required license: Cortex XDR Pro per Endpoint, Cortex XDR Pro, or Cortex XDR Pro per GB.
Base Command
xdr-list-users
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.User.user_email | string | Email address of the user |
| PaloAltoNetworksXDR.User.user_first_name | string | First name of the user |
| PaloAltoNetworksXDR.User.user_last_name | string | Last name of the user. |
| PaloAltoNetworksXDR.User.role_name | string | Role name associated with the user. |
| PaloAltoNetworksXDR.User.last_logged_in | Number | Timestamp of when the user last logged in. |
| PaloAltoNetworksXDR.User.user_type | string | Type of user. |
| PaloAltoNetworksXDR.User.groups | array | Name of user groups associated with the user, if applicable. |
| PaloAltoNetworksXDR.User.scope | array | Name of scope associated with the user, if applicable. |
Command example
#### Context Example
```json
{
"dummy": {
"User": [
{
"groups": [],
"last_logged_in": 1648158415051,
"role_name": "dummy",
"scope": [],
"user_email": "dummy@dummy.com",
"user_first_name": "dummy",
"user_last_name": "dummy",
"user_type": "dummy"
},
{
"groups": [],
"last_logged_in": null,
"role_name": "dummy",
"scope": [],
"user_email": "dummy@dummy.com",
"user_first_name": "dummy",
"user_last_name": "dummy",
"user_type": "dummy"
}
]
}
}
Human Readable Output
Users
First Name Groups Last Name Role Type User email dummy dummy dummy dummy dummy dummy dummy dummy dummy dummy
xdr-list-risky-users
Retrieve the risk score of a specific user or list of users with the highest risk score in the environment along with the reason affecting each score.
Required license: Cortex XDR Pro per Endpoint, Cortex XDR Pro, or Cortex XDR Pro per GB.
Base Command
xdr-list-risky-users
Input
| Argument Name | Description | Required |
|---|---|---|
| user_id | Unique ID of a specific user. User ID could be either of the foo/dummy format, or just dummy.. |
Optional |
| limit | Limit the number of users that will appear in the list. (Use limit when no specific host is requested.). Default is 10. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.RiskyUser.type | String | Form of identification element. |
| PaloAltoNetworksXDR.RiskyUser.id | String | Identification value of the type field. |
| PaloAltoNetworksXDR.RiskyUser.score | Number | The score assigned to the user. |
| PaloAltoNetworksXDR.RiskyUser.reasons.date created | String | Date when the incident was created. |
| PaloAltoNetworksXDR.RiskyUser.reasons.description | String | Description of the incident. |
| PaloAltoNetworksXDR.RiskyUser.reasons.severity | String | The severity of the incident |
| PaloAltoNetworksXDR.RiskyUser.reasons.status | String | The incident status |
| PaloAltoNetworksXDR.RiskyUser.reasons.points | Number | The score. |
Command example
!xdr-list-risky-users user_id=dummy
Context Example
{
"PaloAltoNetworksXDR": {
"RiskyUser": {
"id": "dummy",
"reasons": [],
"score": 0,
"type": "user"
}
}
}
Human Readable Output
Risky Users
User ID Score Description dummy 0
xdr-list-risky-hosts
Retrieve the risk score of a specific host or list of hosts with the highest risk score in the environment along with the reason affecting each score.
Required license: Cortex XDR Pro per Endpoint, Cortex XDR Pro, or Cortex XDR Pro per GB.
Base Command
xdr-list-risky-hosts
Input
| Argument Name | Description | Required |
|---|---|---|
| host_id | The host name of a specific host. | Optional |
| limit | Limit the number of hosts that will appear in the list. By default, the limit is 50 hosts.(Use limit when no specific host is requested.). Default is 10. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.RiskyHost.type | String | Form of identification element. |
| PaloAltoNetworksXDR.RiskyHost.id | String | Identification value of the type field. |
| PaloAltoNetworksXDR.RiskyHost.score | Number | The score assigned to the host. |
| PaloAltoNetworksXDR.RiskyHost.reasons.date created | String | Date when the incident was created. |
| PaloAltoNetworksXDR.RiskyHost.reasons.description | String | Description of the incident. |
| PaloAltoNetworksXDR.RiskyHost.reasons.severity | String | The severity of the incident |
| PaloAltoNetworksXDR.RiskyHost.reasons.status | String | The incident status |
| PaloAltoNetworksXDR.RiskyHost.reasons.points | Number | The score. |
Command example
!xdr-list-risky-hosts host_id=dummy
Context Example
{
"PaloAltoNetworksXDR": {
"RiskyHost": {
"id": "dummy",
"reasons": [],
"score": 0,
"type": "dummy"
}
}
}
Human Readable Output
Risky Hosts
Host ID Score Description dummy 0
xdr-list-user-groups
Retrieve a list of the current user emails associated with one or more user groups in the environment.
Required license: Cortex XDR Pro per Endpoint, Cortex XDR Pro, or Cortex XDR Pro per GB.
Base Command
xdr-list-user-groups
Input
| Argument Name | Description | Required |
|---|---|---|
| group_names | A comma-separated list of one or more user group names for which you want the associated users. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.UserGroup.group_name | String | Name of the user group. |
| PaloAltoNetworksXDR.UserGroup.description | String | Description of the user group, if available. |
| PaloAltoNetworksXDR.UserGroup.pretty_name | String | Name of the user group as it appears in the management console. |
| PaloAltoNetworksXDR.UserGroup.insert_time | Number | Timestamp of when the user group was created. |
| PaloAltoNetworksXDR.UserGroup.update_time | Number | Timestamp of when the user group was last updated. |
| PaloAltoNetworksXDR.UserGroup.user_email | array | List of email addresses belonging to the users associated with the user group. |
| PaloAltoNetworksXDR.UserGroup.source | String | Type of user group. |
Command example
!xdr-list-user-groups group_names=test
Context Example
{
"PaloAltoNetworksXDR": {
"UserGroup": {
"description": "test",
"group_name": "test",
"insert_time": 1684746187678,
"pretty_name": null,
"source": "Custom",
"update_time": 1684746209062,
"user_email": [
null
]
}
}
}
Human Readable Output
Groups
Group Name Group Description User email test test for demo
xdr-list-roles
Retrieve information about one or more roles created in the environment.
Required license: Cortex XDR Pro per Endpoint, Cortex XDR Pro, or Cortex XDR Pro per GB.
Base Command
xdr-list-roles
Input
| Argument Name | Description | Required |
|---|---|---|
| role_names | A comma-separated list of one or more role names in your environment for which you want detailed information. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.Role.pretty_name | String | Name of the role as it appears in the management console. |
| PaloAltoNetworksXDR.Role.permissions | array | List of permissions associated with this role. |
| PaloAltoNetworksXDR.Role.insert_time | Number | Timestamp of when the role was created. |
| PaloAltoNetworksXDR.Role.update_time | Number | Timestamp of when the role was last updated. |
| PaloAltoNetworksXDR.Role.created_by | String | Email of the user who created the role. |
| PaloAltoNetworksXDR.Role.description | String | Description of the role, if available. |
| PaloAltoNetworksXDR.Role.groups | array | Group names associated with the role. |
| PaloAltoNetworksXDR.Role.users | array | Email address of users associated with the role. |
Command example
!xdr-list-roles role_names=dummy
Context Example
{
"PaloAltoNetworksXDR": {
"Role": [
[
{
"created_by": "dummy dummy",
"description": "The user(s) have full access.",
"groups": [],
"insert_time": null,
"permissions": [
"dummy"
],
"pretty_name": "dummy",
"update_time": null,
"users": []
}
]
]
}
}
Human Readable Output
Roles
Role Name Description Permissions Users Groups dummy The user(s) have full access. ADMIN
xdr-set-user-role
Add one or more users to a role.
Required license: Cortex XDR Pro per Endpoint, Cortex XDR Pro, or Cortex XDR Pro per GB.
Base Command
xdr-set-user-role
Input
| Argument Name | Description | Required |
|---|---|---|
| user_emails | A comma-separated list of one or more user emails of users you want to add to a role. | Required |
| role_name | Name of the role you want to add a user to. | Required |
Context Output
There is no context output for this command.
Command example
!xdr-set-user-role role_name=dummy user_emails=dummy
Human Readable Output
Role was updated successfully for 1 user.
xdr-remove-user-role
Remove one or more users from a role.
Required license: Cortex XDR Pro per Endpoint, Cortex XDR Pro, or Cortex XDR Pro per GB.
Base Command
xdr-remove-user-role
Input
| Argument Name | Description | Required |
|---|---|---|
| user_emails | A comma-separate list of one or more user emails of users you want to remove from a role. | Required |
Context Output
There is no context output for this command.
Command example
!xdr-remove-user-role user_emails=dummy
Human Readable Output
Role was removed successfully for 1 user.
xdr-script-run
Initiates a new endpoint script execution action using a script from the script library and returns the results.
Required Permissions
Required Permissions For API call:
Agent Scripts library –> View
Builtin Roles with this permission includes: “Privileged Responder”, “Viewer” and “Instance Admin”.
Base Command
xdr-script-run
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | Allows linking the response action to the incident that triggered it. | Optional |
| endpoint_ids | A comma-separated list of endpoint IDs. Can be retrieved by running the xdr-get-endpoints command. | Required |
| script_uid | Unique identifier of the script. Can be retrieved by running the xdr-get-scripts command. | Required |
| parameters | Dictionary containing the parameter name as key and its value for this execution as the value. For example, {“param1”:”param1_value”,”param2”:”param2_value”}. | Optional |
| timeout | The timeout in seconds for this execution. Default is 600. | Optional |
| polling_interval_in_seconds | Interval in seconds between each poll. Default is 10. | Optional |
| polling_timeout_in_seconds | Polling timeout in seconds. Default is 600. | Optional |
| action_id | action ID for polling. | Optional |
| hide_polling_output | whether to hide the polling result (automatically filled by polling). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.ScriptResult.action_id | Number | ID of the action initiated. |
| PaloAltoNetworksXDR.ScriptResult.results.retrieved_files | Number | Number of successfully retrieved files. |
| PaloAltoNetworksXDR.ScriptResult.results.endpoint_ip_address | String | Endpoint IP address. |
| PaloAltoNetworksXDR.ScriptResult.results.endpoint_name | String | Number of successfully retrieved files. |
| PaloAltoNetworksXDR.ScriptResult.results.failed_files | Number | Number of files failed to retrieve. |
| PaloAltoNetworksXDR.ScriptResult.results.endpoint_status | String | Endpoint status. |
| PaloAltoNetworksXDR.ScriptResult.results.domain | String | Domain to which the endpoint belongs. |
| PaloAltoNetworksXDR.ScriptResult.results.endpoint_id | String | Endpoint ID. |
| PaloAltoNetworksXDR.ScriptResult.results.execution_status | String | Execution status of this endpoint. |
| PaloAltoNetworksXDR.ScriptResult.results.return_value | String | Value returned by the script in case the type is not a dictionary. |
| PaloAltoNetworksXDR.ScriptResult.results.standard_output | String | The STDOUT and the STDERR logged by the script during the execution. |
| PaloAltoNetworksXDR.ScriptResult.results.retention_date | Date | Timestamp in which the retrieved files will be deleted from the server. |
Base Command
xdr-script-run
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | Allows linking the response action to the incident that triggered it. | Optional |
| endpoint_ids | A comma-separated list of endpoint IDs. Can be retrieved by running the xdr-get-endpoints command. | Required |
| script_uid | Unique identifier of the script. Can be retrieved by running the xdr-get-scripts command. | Required |
| parameters | Dictionary containing the parameter name as key and its value for this execution as the value. For example, {“param1”:”param1_value”,”param2”:”param2_value”}. | Optional |
| timeout | The timeout in seconds for this execution. Default is 600. | Optional |
| polling_interval_in_seconds | Interval in seconds between each poll. Default is 10. | Optional |
| polling_timeout_in_seconds | Polling timeout in seconds. Default is 600. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.ScriptResult.action_id | Number | ID of the action initiated. |
| PaloAltoNetworksXDR.ScriptResult.results.retrieved_files | Number | Number of successfully retrieved files. |
| PaloAltoNetworksXDR.ScriptResult.results.endpoint_ip_address | String | Endpoint IP address. |
| PaloAltoNetworksXDR.ScriptResult.results.endpoint_name | String | Number of successfully retrieved files. |
| PaloAltoNetworksXDR.ScriptResult.results.failed_files | Number | Number of files failed to retrieve. |
| PaloAltoNetworksXDR.ScriptResult.results.endpoint_status | String | Endpoint status. |
| PaloAltoNetworksXDR.ScriptResult.results.domain | String | Domain to which the endpoint belongs. |
| PaloAltoNetworksXDR.ScriptResult.results.endpoint_id | String | Endpoint ID. |
| PaloAltoNetworksXDR.ScriptResult.results.execution_status | String | Execution status of this endpoint. |
| PaloAltoNetworksXDR.ScriptResult.results.return_value | String | Value returned by the script in case the type is not a dictionary. |
| PaloAltoNetworksXDR.ScriptResult.results.standard_output | String | The STDOUT and the STDERR logged by the script during the execution. |
| PaloAltoNetworksXDR.ScriptResult.results.retention_date | Date | Timestamp in which the retrieved files will be deleted from the server. |
Command example
!xdr-script-run endpoint_ids=1 script_uid=123
Human Readable Output
Waiting for the script to finish running on the following endpoints: [‘1’]…
Script Execution Results - 10368
_return_value domain endpoint_id endpoint_ip_address endpoint_name endpoint_status execution_status failed_files retention_date retrieved_files standard_output Name: return value WORKGROUP 1 1.1.1.1 WIN10X64 STATUS_010_CONNECTED COMPLETED_SUCCESSFULLY 0 0
Context Example
{
"PaloAltoNetworksXDR": {
"ScriptResult": {
"results": [
{
"domain": "WORKGROUP",
"endpoint_name": "WIN10X64",
"retrieved_files": 0,
"failed_files": 0,
"standard_output": "",
"_return_value": [
"return_value"
],
"command_output": [
"command_output"
],
"endpoint_status": "STATUS_010_CONNECTED",
"command": "_return_value",
"endpoint_id": "1",
"endpoint_ip_address": [
"1.1.1.1"
],
"execution_status": "COMPLETED_SUCCESSFULLY",
"retention_date": null
}
],
"action_id": 4444
}
}
}
xdr-endpoint-tag-add
Adds a tag to specified endpoint_ids
Required Permissions
Required Permissions For API call:
Endpoint Administrations –> View/ Edit
Builtin Roles with this permission includes: “Privileged Responder” and “Instance Admin”.
Base Command
xdr-endpoint-tag-add
Input
| Argument Name | Description | Required |
|---|---|---|
| endpoint_ids | List of endpoint IDs. Supports comma-separated list. | Optional |
| tag | Tag to add. | Optional |
Context Output
There is no context output for this command.
xdr-endpoint-tag-remove
Removes a tag from specified endpoint_ids.
Required Permissions
Required Permissions For API call:
Endpoint Administrations –> View/ Edit
Builtin Roles with this permission includes: “Privileged Responder” and “Instance Admin”.
Base Command
xdr-endpoint-tag-remove
Input
| Argument Name | Description | Required |
|---|---|---|
| endpoint_ids | List of endpoint IDs. Supports comma separated list. | Optional |
| tag | Tag to remove from specified endpoint_ids. | Optional |
Context Output
There is no context output for this command.
xdr-get-tenant-info
Provides information about the tenant.
Base Command
xdr-get-tenant-info
Input
There are no arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.TenantInformation.pro_per_endpoint_expiration | Date | Expiration time pro per endpoint. |
| PaloAltoNetworksXDR.TenantInformation.purchased_pro_per_endpoint.agents | Number | Number of endpoints agent purchased. |
| PaloAltoNetworksXDR.TenantInformation.data_enabled_pro_per_endpoint | Number | Enabled data per pro endpoint. |
| PaloAltoNetworksXDR.TenantInformation.prevent_expiration | Number | Number of prevent expirations. |
| PaloAltoNetworksXDR.TenantInformation.purchased_prevent | Number | Number of purchased prevents. |
| PaloAltoNetworksXDR.TenantInformation.installed_prevent | Number | Number of installed prevents. |
| PaloAltoNetworksXDR.TenantInformation.pro_tb_expiration | Date | pro_tb license expiration time. |
| PaloAltoNetworksXDR.TenantInformation.purchased_pro_tb.tb | Number | Number of pro_tbs purchased. |
| PaloAltoNetworksXDR.TenantInformation.installed_pro_tb | Number | Number of pro_tbs installed. |
| PaloAltoNetworksXDR.TenantInformation.compute_unit_expiration | Date | Compute unit expiration time. |
| PaloAltoNetworksXDR.TenantInformation.purchased_compute_unit | Number | Number of compute units purchased. |
| PaloAltoNetworksXDR.TenantInformation.compute_unit_is_trial | Boolean | Whether the compute unit is a trial. |
| PaloAltoNetworksXDR.TenantInformation.host_insights_expiration | Date | Host insight expiration time. |
| PaloAltoNetworksXDR.TenantInformation.enabled_host_insights | Number | Number of host insights enabled. |
| PaloAltoNetworksXDR.TenantInformation.purchased_host_insights | Number | Number of purchased host insights. |
| PaloAltoNetworksXDR.TenantInformation.forensics_expiration | Date | Forensic expiration time. |
| PaloAltoNetworksXDR.TenantInformation.purchased_forensics | Number | Number of forensics purchased. |
Command example
#### Context Example
```json
{
"PaloAltoNetworksXDR": {
"TenantInformation": {
"compute_unit_expiration": 0,
"data_enabled_pro_per_endpoint": 2,
"forensics_expiration": 0,
"installed_prevent": 2,
"installed_pro_tb": 0,
"prevent_expiration": 0,
"pro_per_endpoint_expiration": "May 7th 2025 06:59:59",
"pro_tb_expiration": "May 7th 2025 06:59:59",
"purchased_compute_unit": 2000,
"purchased_prevent": 0,
"purchased_pro_per_endpoint": {
"agents": 300
},
"purchased_pro_tb": {
"tb": 1
}
}
}
}
Human Readable Output
Tenant Information
Compute Unit Expiration Data Enabled Pro Per Endpoint Forensics _ Expiration Installed _ Prevent Installed Pro Tb Prevent _ Expiration Pro Per Endpoint _ Expiration Pro Tb Expiration Purchased Compute Unit Purchased _ Prevent Purchased Pro Per _ Endpoint Purchased Pro Tb May 7th 2025 06:59:59 May 7th 2025 06:59:59 agents: 300 tb: 1
Incident Mirroring
You can enable incident mirroring between Cortex XSOAR incidents and Palo Alto Networks Cortex XDR - Investigation and Response corresponding events (available from Cortex XSOAR version 6.0.0).
To set up the mirroring:
- Enable Fetching incidents in your instance configuration.
-
In the Mirroring Direction integration parameter, select in which direction the incidents should be mirrored:
Option Description None Turns off incident mirroring. Incoming Any changes in Palo Alto Networks Cortex XDR - Investigation and Response events (mirroring incoming fields) will be reflected in Cortex XSOAR incidents. Outgoing Any changes in Cortex XSOAR incidents will be reflected in Palo Alto Networks Cortex XDR - Investigation and Response events (outgoing mirrored fields). Both
Newly fetched incidents will be mirrored in the chosen direction. However, this selection does not affect existing incidents.
Important Note: To ensure the mirroring works as expected, mappers are required, both for incoming and outgoing, to map the expected fields in Cortex XSOAR and Palo Alto Networks Cortex XDR - Investigation and Response.
xdr-endpoint-alias-change
Gets a list of endpoints according to the passed filters, and changes their alias name. Filtering by multiple fields will be concatenated using the AND condition (OR is not supported).
Base Command
xdr-endpoint-alias-change
Input
| Argument Name | Description | Required |
|---|---|---|
| status | The status of the endpoint to use as a filter. Possible values are: connected, disconnected. | Optional |
| endpoint_id_list | A comma-separated list of endpoint IDs to use as a filter. | Optional |
| dist_name | A comma-separated list of distribution package names or installation package names to use as a filter. Example: dist_name1,dist_name2. |
Optional |
| ip_list | A comma-separated list of IP addresses to use as a filter. Example: 8.8.8.8,1.1.1.1. |
Optional |
| group_name | A comma-separated list of group names to which the agent belongs to use as a filter. Example: group_name1,group_name2. |
Optional |
| platform | The endpoint platform to use as a filter. Possible values are: windows, linux, macos, android. | Optional |
| alias_name | A comma-separated list of alias names to use as a filter. Examples: alias_name1,alias_name2. |
Optional |
| isolate | Specifies whether the endpoint was isolated or unisolated to use as a filter. Possible values are: isolated, unisolated. Note: This argument returns only the first endpoint that matches the filter. | Optional |
| hostname | A comma-separated list of hostnames to use as a filter. Example: hostname1,hostname2. |
Optional |
| first_seen_gte | All the agents that were first seen after {first_seen_gte} to use as a filter. Supported values: 1579039377301 (time in milliseconds) “3 days” (relative date) “2019-10-21T23:45:00” (date). |
Optional |
| first_seen_lte | All the agents that were first seen before {first_seen_lte} to use as a filter. Supported values: 1579039377301 (time in milliseconds) “3 days” (relative date) “2019-10-21T23:45:00” (date). |
Optional |
| last_seen_gte | All the agents that were last seen after {last_seen_gte} to use as a filter. Supported values: 1579039377301 (time in milliseconds) “3 days” (relative date) “2019-10-21T23:45:00” (date). |
Optional |
| last_seen_lte | All the agents that were last seen before {last_seen_lte} to use as a filter. Supported values: 1579039377301 (time in milliseconds) “3 days” (relative date) “2019-10-21T23:45:00” (date). |
Optional |
| username | The usernames to query for to use as a filter. Accepts a single user, or comma-separated list of usernames. | Optional |
| new_alias_name | The alias name to change to. Note: If you send an empty field, (e.g new_alias_name="") the current alias name is deleted. | Required |
| scan_status | The scan status of the endpoint to use as a filter. Possible values are: none, pending, in_progress, canceled, aborted, pending_cancellation, success, error. | Optional |
Context Output
There is no context output for this command.
Command example
!xdr-endpoint-alias-change new_alias_name=test scan_status=success ip_list=1.1.1.1
Human Readable Output
The endpoint alias was changed successfully.
Note: If there is no error in the process, then this is the output even when the specific endpoint does not exist.
xdr-update-alert (Deprecated)
This command is deprecated, please use xdr-issue-update instead. Update one or more alerts. You can update up to 100 alerts per request. Missing fields are ignored. Required license: Cortex XDR Prevent, Cortex XDR Pro per Endpoint, or Cortex XDR Pro per GB.
Base Command
xdr-update-alert
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_ids | Comma-separated list of alert IDs. | Required |
| severity | Severity of the incident which was closed. Possible values are: critical, high, medium, low. | Optional |
| status | New status for updated alerts. Possible values are: new, resolved_threat_handled, under_investigation, resolved_security_testing, resolved_auto, resolved_auto_resolve, resolved_known_issue, resolved_duplicate, resolved_other, resolved_false_positive, resolved_true_positive. | Optional |
| comment | Comment to append to updated alerts. | Optional |
Context Output
There is no context output for this command.
Command example
!xdr-update-alert alert_ids=35326 severity=low
Human Readable Output
Alerts with IDs 35326 have been updated successfully.
xdr-asset-group-update
Updates an asset group.
Base Command
xdr-asset-group-update
Input
| Argument Name | Description | Required |
|---|---|---|
| group_id | The ID of the asset group to update. | Required |
| group_name | The name of the asset group. | Optional |
| group_type | The type of the asset group. Possible values are: Static, Dynamic. | Optional |
| group_description | The description of the asset group. | Optional |
| membership_predicate_json | Define the filter conditions for selecting which assets to be included in a dynamic Asset Group. For example: “{"AND":[{"SEARCH_FIELD":"xdm.asset.type.class","SEARCH_TYPE":"NEQ","SEARCH_VALUE":"Other"}]}”. The SEARCH_FIELD needs to be in lower case. For more information, please refer to the documentation: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Update-an-Asset-Group. | Optional |
Context Output
There is no context output for this command.
xdr-asset-group-create
Creates an asset group.
Base Command
xdr-asset-group-create
Input
| Argument Name | Description | Required |
|---|---|---|
| group_name | The name of the asset group. | Required |
| group_type | The type of the asset group. Possible values are: Static, Dynamic. | Required |
| group_description | The description of the asset group. | Optional |
| membership_predicate_json | Define the filter conditions for selecting which assets to be included in a dynamic Asset Group. For example: “{"AND":[{"SEARCH_FIELD":"xdm.asset.type.class","SEARCH_TYPE":"NEQ","SEARCH_VALUE":"Other"}]}”. The SEARCH_FIELD needs to be in lower case. For more information, please refer to the documentation: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Create-an-Asset-Group. | Optional |
Context Output
There is no context output for this command.
xdr-asset-group-list
Returns a list of asset groups.
Base Command
xdr-asset-group-list
Input
| Argument Name | Description | Required |
|---|---|---|
| sort_field | The field by which to sort the results. For example: XDM.ASSET_GROUP.NAME. Use the documentation for finding more fields here. | Optional |
| sort_order | The order in which to sort the results. Possible values are: asc, desc. | Optional |
| filter_json | The JSON to use for the “filter” field in the API. For example: “{"AND": [{"SEARCH_FIELD": "XDM.ASSET_GROUP.TYPE", "SEARCH_TYPE": "EQ", "SEARCH_VALUE": "Dynamic"}]}”. For more information, please refer to the documentation: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Get-all-or-filtered-asset-groups. | Optional |
| limit | Maximum number of asset groups to return. Default is 50. Default is 50. | Optional |
| page_size | Page size for pagination. | Optional |
| page | Page number for pagination. 0 is the first page. Default is 0. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.AssetGroup.XDM_ASSET_GROUP_ID | String | The unique identifier of the asset group. |
| PaloAltoNetworksXDR.AssetGroup.XDM_ASSET_GROUP_NAME | String | The name of the asset group. |
| PaloAltoNetworksXDR.AssetGroup.XDM_ASSET_GROUP_TYPE | String | The type of the asset group (Static or Dynamic). |
| PaloAltoNetworksXDR.AssetGroup.XDM_ASSET_GROUP_FILTER | String | The filter query string used to define the members of the XDM asset group. |
| PaloAltoNetworksXDR.AssetGroup.XDM_ASSET_GROUP_DESCRIPTION | String | The description of the asset group. |
| PaloAltoNetworksXDR.AssetGroup.XDM_ASSET_GROUP_CREATION_TIME | Date | The timestamp when the group was created (Epoch). |
| PaloAltoNetworksXDR.AssetGroup.XDM_ASSET_GROUP_LAST_UPDATE_TIME | Date | The timestamp when the group was last updated (Epoch). |
| PaloAltoNetworksXDR.AssetGroup.XDM_ASSET_GROUP_CREATED_BY_PRETTY | String | The user or API key that created the group. |
| PaloAltoNetworksXDR.AssetGroup.XDM_ASSET_GROUP_MODIFIED_BY_PRETTY | String | The user or API key that last modified the group. |
| PaloAltoNetworksXDR.AssetGroup.XDM_ASSET_GROUP_MEMBERSHIP_PREDICATE | Unknown | The JSON object defining the search criteria for dynamic groups. |
| PaloAltoNetworksXDR.AssetGroup.IS_USED_BY_SBAC | Boolean | Indicates whether this asset group is currently utilized to define Scope-Based Access Control (SBAC) rules. |
xdr-asset-group-delete
Deletes an asset group.
Base Command
xdr-asset-group-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| group_id | The ID of the asset group to delete. | Required |
Context Output
There is no context output for this command.
xdr-asset-schema-field-options-get
Gets the enum values of a specified field in the asset schema.
Base Command
xdr-asset-schema-field-options-get
Input
| Argument Name | Description | Required |
|---|---|---|
| field_name | The name of the field to get options for. You can use xdr-asset-schema-get in order to get the schema. The field must be of type ENUM, for example: xdm.asset.provider. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.AssetSchema.field_name | String | The name of the field. |
| PaloAltoNetworksXDR.AssetSchema.options | Unknown | The enum values of the field. |
xdr-asset-schema-get
Gets the schema of the asset inventory.
Base Command
xdr-asset-schema-get
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.AssetSchema.field_name | String | The name of the field. |
| PaloAltoNetworksXDR.AssetSchema.field_type | String | The type of the field. |
| PaloAltoNetworksXDR.AssetSchema.field_pretty_name | String | The pretty name of the field. |
xdr-asset-list
Returns a list of assets.
Base Command
xdr-asset-list
Input
| Argument Name | Description | Required |
|---|---|---|
| asset_id | A comma-separated list of asset IDs. For example: “1,2,3”. When using this argument, the other filters will not be used. | Optional |
| sort_field | The field by which to sort the results. For example: xdm.asset.first_observed. Use the documentation for finding more fields here. | Optional |
| sort_order | The order in which to sort the results. Possible values are: asc, desc. | Optional |
| filter_json | The JSON to use for the “filter” field in the API. You can use xdr-asset-schema-get to get the schema. For more information, please refer to the documentation: here. | Optional |
| limit | Maximum number of assets to return. Default is 50. Default is 50. | Optional |
| page_size | Page size for pagination. Default is 50. | Optional |
| page | Page number for pagination. Default is 0. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.Asset.xdm_asset_id | String | The unique identifier of the asset. |
| PaloAltoNetworksXDR.Asset.xdm_asset_name | String | The name of the asset (e.g., image SHA). |
| PaloAltoNetworksXDR.Asset.xdm_asset_strong_id | String | The strong identifier (SHA256) of the asset. |
| PaloAltoNetworksXDR.Asset.xdm_asset_provider | String | The provider of the asset. |
| PaloAltoNetworksXDR.Asset.xdm_asset_external_provider_id | String | External provider ID (if applicable). |
| PaloAltoNetworksXDR.Asset.xdm_asset_first_observed | Date | Timestamp when the asset was first observed. |
| PaloAltoNetworksXDR.Asset.xdm_asset_last_observed | Date | Timestamp when the asset was last observed. |
| PaloAltoNetworksXDR.Asset.xdm_asset_type_id | String | The ID of the asset type (e.g., CORE_IMAGE). |
| PaloAltoNetworksXDR.Asset.xdm_asset_type_name | String | The name of the asset type. |
| PaloAltoNetworksXDR.Asset.xdm_asset_type_category | String | The category of the asset (e.g., Container Image). |
| PaloAltoNetworksXDR.Asset.xdm_asset_type_class | String | The class of the asset (e.g., Compute). |
| PaloAltoNetworksXDR.Asset.xdm_development_cycle_stages | String | The development cycle stages (e.g., RUNTIME). |
| PaloAltoNetworksXDR.Asset.xdm_image_architecture | String | The architecture of the image (e.g., amd64). |
| PaloAltoNetworksXDR.Asset.xdm_image_digest | String | The image digest hash. |
| PaloAltoNetworksXDR.Asset.xdm_image_identifier | String | The image identifier. |
| PaloAltoNetworksXDR.Asset.xdm_image_names | String | List of names/tags associated with the image. |
| PaloAltoNetworksXDR.Asset.xdm_image_os | String | The OS version of the image. |
| PaloAltoNetworksXDR.Asset.xdm_image_os_distribution | String | The OS distribution (e.g., UBUNTU). |
| PaloAltoNetworksXDR.Asset.xdm_image_os_family | String | The OS family (e.g., Linux). |
| PaloAltoNetworksXDR.Asset.xdm_image_os_release | String | The OS release name (e.g., noble). |
| PaloAltoNetworksXDR.Asset.xdm_image_labels | Unknown | Labels associated with the image. |
| PaloAltoNetworksXDR.Asset.xdm_image_layers | Unknown | List of layers making up the image. |
| PaloAltoNetworksXDR.Asset.xdm_image_layers_created_at | Number | Timestamp of when the layer was created. |
| PaloAltoNetworksXDR.Asset.xdm_image_layers_instruction | String | The instruction used to create the layer (e.g., RUN, ADD). |
| PaloAltoNetworksXDR.Asset.xdm_image_layers_size | Number | The size of the layer in bytes. |
| PaloAltoNetworksXDR.Asset.xdm_asset_related_cases_cases_breakdown | Unknown | Breakdown of related cases by severity. |
| PaloAltoNetworksXDR.Asset.xdm_asset_related_cases_critical_cases | Number | Count of critical cases. |
| PaloAltoNetworksXDR.Asset.xdm_asset_related_issues_issues_breakdown | Unknown | Breakdown of related issues by severity. |
| PaloAltoNetworksXDR.Asset.xdm_asset_relations | Unknown | Relations to other assets. |
| PaloAltoNetworksXDR.Asset.xdm_asset_group_ids | Number | Group IDs associated with the asset. |
xdr-api-key-delete
Deletes the specified API keys.
Base Command
xdr-api-key-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| api_id | A comma-separated list of API key IDs to delete. | Required |
Context Output
There is no context output for this command.
xdr-api-key-list
Gets a list of existing API keys.
Base Command
xdr-api-key-list
Input
| Argument Name | Description | Required |
|---|---|---|
| api_id | A comma-separated list of API key IDs to retrieve. | Optional |
| role | A comma-separated list of API key roles to retrieve. | Optional |
| expires_before | Filters API keys that expire before this date. For example: “1 year”. Filters API keys that have an expiration date. | Optional |
| expires_after | Filters API keys that expire after this date. For example: “1 year”. Filters API keys that have an expiration date. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.APIKeyData.id | String | The API key ID. |
| PaloAltoNetworksXDR.APIKeyData.roles | String | The roles associated with the API key. |
| PaloAltoNetworksXDR.APIKeyData.expiration | Date | The expiration date of the API key. |
xdr-bioc-list
Returns a list of BIOCs.
Base Command
xdr-bioc-list
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The BIOC name to filter by. Can filter by only one name at a time. | Optional |
| severity | The BIOC severity to filter by. Possible values are: info, low, medium, high, critical. | Optional |
| type | The BIOC type to filter by. Possible values are: other, persistence, evasion, tampering, file_type_obfuscation, privilege_escalation, credential_access, lateral_movement, execution, collection, exfiltration, infiltration, dropper, file_privilege_manipulation, reconnaissance, discovery. | Optional |
| is_xql | Whether the BIOC is XQL. Possible values are: true, false. | Optional |
| comment | The BIOC comment to filter by. | Optional |
| status | The BIOC status to filter by. Possible values are: enabled, disabled. | Optional |
| indicator | The BIOC indicator to filter by. | Optional |
| mitre_technique_id_and_name | The MITRE technique ID and name. Must be in format ‘ID - Name’, for example: [‘T1566 - Phishing’]. | Optional |
| mitre_tactic_id_and_name | The MITRE tactic ID and name. Must be in format ‘ID - Name’, for example: [‘T1566 - Phishing’]. | Optional |
| extra_data | Whether to return extended data. Possible values are: true, false. | Optional |
| limit | Maximum number of results to return. | Optional |
| page_size | Page size. | Optional |
| page | Page number. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.BIOC.rule_id | String | BIOC rule ID. |
| PaloAltoNetworksXDR.BIOC.name | String | BIOC name. |
| PaloAltoNetworksXDR.BIOC.type | String | BIOC type. |
| PaloAltoNetworksXDR.BIOC.severity | String | BIOC severity. |
| PaloAltoNetworksXDR.BIOC.status | String | BIOC status. |
| PaloAltoNetworksXDR.BIOC.is_xql | Boolean | Whether the BIOC is XQL. |
| PaloAltoNetworksXDR.BIOC.comment | String | The BIOC comment. |
| PaloAltoNetworksXDR.BIOC.indicator | String | The BIOC indicator. |
xdr-bioc-create
Creates a new BIOC.
Base Command
xdr-bioc-create
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The BIOC name. | Required |
| severity | The BIOC severity. Possible values are: info, low, medium, high, critical. | Required |
| type | The BIOC type. Possible values are: other, persistence, evasion, tampering, file_type_obfuscation, privilege_escalation, credential_access, lateral_movement, execution, collection, exfiltration, infiltration, dropper, file_privilege_manipulation, reconnaissance, discovery. | Optional |
| is_xql | Whether the new BIOC is XQL. Possible values are: true, false. | Optional |
| comment | The BIOC comment. | Optional |
| status | The BIOC status. Possible values are: enabled, disabled. | Optional |
| indicator | The BIOC indicator, for example: ‘{“runOnCGO”:true,”investigationType”:”FILE_EVENT”,”investigation”:{“FILE_EVENT”:{“filter”:{“AND”:[{“SEARCH_FIELD”:”action_file_name”,”SEARCH_TYPE”:”EQ”,”SEARCH_VALUE”:”testfile.exe”}]}}}}’. For more information, refer to the documentation here. |
Required |
| mitre_technique_id_and_name | The MITRE technique ID and name. Must be in format ‘ID - Name’, for example: [‘T1566 - Phishing’]. | Optional |
| mitre_tactic_id_and_name | The MITRE tactic ID and name. Must be in format ‘ID - Name’, for example: [‘TA0001 - Initial Access’]. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.BIOC.rule_id | String | BIOC ID. |
xdr-bioc-update
Updates an existing BIOC.
Base Command
xdr-bioc-update
Input
| Argument Name | Description | Required |
|---|---|---|
| rule_id | BIOC rule ID. | Required |
| name | BIOC name. | Required |
| severity | BIOC severity. Possible values are: info, low, medium, high, critical. | Required |
| type | BIOC type. Possible values are: other, persistence, evasion, tampering, file_type_obfuscation, privilege_escalation, credential_access, lateral_movement, execution, collection, exfiltration, infiltration, dropper, file_privilege_manipulation, reconnaissance, discovery. | Optional |
| is_xql | Whether the BIOC is XQL. Possible values are: true, false. | Optional |
| comment | BIOC comment. | Optional |
| status | BIOC status. Possible values are: enabled, disabled. | Optional |
| indicator | The BIOC indicator, for example: ‘{“runOnCGO”:true,”investigationType”:”FILE_EVENT”,”investigation”:{“FILE_EVENT”:{“filter”:{“AND”:[{“SEARCH_FIELD”:”action_file_name”,”SEARCH_TYPE”:”EQ”,”SEARCH_VALUE”:”testfile.exe”}]}}}}’. For more information, refer to the documentation here. |
Required |
| mitre_technique_id_and_name | The MITRE technique ID and name. Must be in format ‘ID - Name’, for example: [‘T1566 - Phishing’]. | Optional |
| mitre_tactic_id_and_name | The MITRE tactic ID and name. Must be in format ‘ID - Name’, for example: [‘TA0001 - Initial Access’]. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.BIOC.rule_id | String | BIOC ID. |
xdr-bioc-delete
Deletes a BIOC.
Base Command
xdr-bioc-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| name | BIOC name. | Optional |
| severity | BIOC severity. Possible values are: info, low, medium, high, critical. | Optional |
| type | BIOC type. Possible values are: other, persistence, evasion, tampering, file_type_obfuscation, privilege_escalation, credential_access, lateral_movement, execution, collection, exfiltration, infiltration, dropper, file_privilege_manipulation, reconnaissance, discovery. | Optional |
| is_xql | Whether the BIOC is XQL. Possible values are: true, false. | Optional |
| comment | BIOC comment. | Optional |
| indicator | BIOC indicator. | Optional |
| mitre_technique_id_and_name | The MITRE technique ID and name. Must be in format ‘ID - Name’, for example: [‘T1566 - Phishing’]. | Optional |
| mitre_tactic_id_and_name | The MITRE tactic ID and name. Must be in format ‘ID - Name’, for example: [‘TA0001 - Initial Access’]. | Optional |
Context Output
There is no context output for this command.
xdr-correlation-rule-list
Returns a list of correlation rules.
Base Command
xdr-correlation-rule-list
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Correlation rule name. | Optional |
| severity | Correlation rule severity. Possible values are: info, low, medium, high, critical. | Optional |
| xql_query | Correlation rule XQL query. | Optional |
| is_xql | Whether the correlation rule is XQL. Possible values are: true, false. | Optional |
| dataset | Correlation rule dataset. | Optional |
| alert_name | Alert name. | Optional |
| alert_category | Alert category. | Optional |
| alert_fields | Alert fields. Can be a string or a dictionary. | Optional |
| alert_domain | Alert domain. | Optional |
| filter_json | Filter JSON. | Optional |
| extra_data | Whether to return extended view. Possible values are: true, false. | Optional |
| limit | Maximum number of results to return. | Optional |
| page_size | Page size. | Optional |
| page | Page number. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.CorrelationRule.suppression_duration | String | The duration for which alerts are suppressed. |
| PaloAltoNetworksXDR.CorrelationRule.alert_category | String | The category of the alert (e.g., DROPPER). |
| PaloAltoNetworksXDR.CorrelationRule.mitre_defs | Unknown | MITRE ATT&CK definitions associated with the rule. |
| PaloAltoNetworksXDR.CorrelationRule.simple_schedule | String | The frequency at which the rule runs in a human-readable format. |
| PaloAltoNetworksXDR.CorrelationRule.mapping_strategy | String | The strategy used for field mapping. |
| PaloAltoNetworksXDR.CorrelationRule.suppression_fields | String | Fields used to determine alert suppression. |
| PaloAltoNetworksXDR.CorrelationRule.alert_domain | String | The security domain the alert belongs to. |
| PaloAltoNetworksXDR.CorrelationRule.crontab | String | The cron expression for the rule execution schedule. |
| PaloAltoNetworksXDR.CorrelationRule.search_window | String | The time window the query searches across. |
| PaloAltoNetworksXDR.CorrelationRule.user_defined_severity | String | Custom severity level defined by the user. |
| PaloAltoNetworksXDR.CorrelationRule.drilldown_query_timeframe | String | The timeframe used for drilldown queries. |
| PaloAltoNetworksXDR.CorrelationRule.user_defined_category | String | Custom category defined by the user. |
| PaloAltoNetworksXDR.CorrelationRule.lookup_mapping | String | Mapping details for lookups. |
| PaloAltoNetworksXDR.CorrelationRule.execution_mode | String | How the rule is executed, for example: SCHEDULED. |
| PaloAltoNetworksXDR.CorrelationRule.name | String | The name of the correlation rule. |
| PaloAltoNetworksXDR.CorrelationRule.is_enabled | Boolean | Whether the correlation rule is currently active. |
| PaloAltoNetworksXDR.CorrelationRule.investigation_query_link | String | The query used for further investigation. |
| PaloAltoNetworksXDR.CorrelationRule.alert_name | String | The specific name assigned to the generated alert. |
| PaloAltoNetworksXDR.CorrelationRule.suppression_enabled | Boolean | Whether suppression is enabled for this rule. |
| PaloAltoNetworksXDR.CorrelationRule.action | String | The action taken when the rule triggers, for example: ALERTS. |
| PaloAltoNetworksXDR.CorrelationRule.dataset | String | The dataset the rule queries. |
| PaloAltoNetworksXDR.CorrelationRule.alert_description | String | Detailed description of the generated alert. |
| PaloAltoNetworksXDR.CorrelationRule.timezone | String | The timezone used for the rule schedule. |
| PaloAltoNetworksXDR.CorrelationRule.xql_query | String | The XQL query string executed by the rule. |
| PaloAltoNetworksXDR.CorrelationRule.alert_fields | Unknown | Specific fields included in the alert output. |
| PaloAltoNetworksXDR.CorrelationRule.description | String | General description of the correlation rule. |
| PaloAltoNetworksXDR.CorrelationRule.alert_type | String | The type of alert generated. |
| PaloAltoNetworksXDR.CorrelationRule.severity | String | The severity level of the rule. |
| PaloAltoNetworksXDR.CorrelationRule.rule_id | Number | The unique identifier for the correlation rule. |
xdr-correlation-rule-create
Creates a new correlation rule.
Base Command
xdr-correlation-rule-create
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The correlation rule name. | Required |
| severity | The correlation rule severity. Example: severity=low. Possible values are: info, low, medium, high, critical. | Required |
| xql_query | The correlation rule XQL query. Example: xql_query=”dataset = xdr_data | limit 1”. | Required |
| is_enabled | Whether the rule is enabled. Example: is_enabled=true. Possible values are: true, false. | Required |
| alert_category | The alert category. Example: alert_category=dropper. Possible values are: other, persistence, evasion, tampering, file_type_obfuscation, privilege_escalation, credential_access, lateral_movement, execution, collection, exfiltration, infiltration, dropper, file_privilege_manipulation, reconnaissance, discovery. | Required |
| execution_mode | The rule execution mode. Example: execution_mode=scheduled. Possible values are: scheduled, real_time. | Required |
| timezone | The correlation rule timezone. Example: timezone=”Asia/Jerusalem”. | Required |
| mapping_strategy | The rule mapping strategy. Example: mapping_strategy=auto. Possible values are: auto, custom. | Required |
| description | The correlation rule description. | Optional |
| alert_name | The alert name. | Optional |
| alert_description | The alert description. | Optional |
| alert_fields | Alert fields (string or dictionary). | Optional |
| search_window | The search window timeframe. Example: search_window=”1 hours”. | Optional |
| schedule | The correlation rule schedule. Example: schedule=”10 minutes”. | Optional |
| schedule_linux | Linux scheduling for the rule. Example: schedule_linux=”/10 ** *”. | Optional |
| suppression_enabled | Whether suppression is enabled. Possible values are: true, false. | Optional |
| suppression_duration | Duration of correlation rule suppression. | Optional |
| suppression_fields | Suppression fields. | Optional |
| dataset | The correlation rule dataset. Example: dataset=alerts. | Required |
| user_defined_severity | User-defined severity. | Optional |
| user_defined_category | User-defined category. | Optional |
| mitre_defs_json | MITRE definitions. For example: ‘{“TA0005 - Defense Evasion”: [“T1014 - Rootkit”]}’. | Optional |
| investigation_query_link | Investigation query link. | Optional |
| drilldown_query_timeframe | The drilldown query timeframe. Example: drilldown_query_timeframe=”ALERT”. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.CorrelationRule.rule_id | String | Correlation rule ID. |
xdr-correlation-rule-update
Updates an existing correlation rule.
Base Command
xdr-correlation-rule-update
Input
| Argument Name | Description | Required |
|---|---|---|
| rule_id | Correlation rule ID. | Required |
| name | The correlation rule name. | Required |
| severity | The correlation rule severity. Example: severity=low. Possible values are: info, low, medium, high, critical. | Required |
| xql_query | The correlation rule XQL query. Example: xql_query=”dataset = xdr_data | limit 1”. | Required |
| is_enabled | Whether the rule is enabled. Example: is_enabled=true. Possible values are: true, false. | Required |
| alert_category | The alert category. Example: alert_category=dropper. Possible values are: other, persistence, evasion, tampering, file_type_obfuscation, privilege_escalation, credential_access, lateral_movement, execution, collection, exfiltration, infiltration, dropper, file_privilege_manipulation, reconnaissance, discovery. | Required |
| execution_mode | The rule execution mode. Example: execution_mode=scheduled. Possible values are: scheduled, real_time. | Required |
| timezone | The correlation rule timezone. Example: timezone=”Asia/Jerusalem”. | Required |
| mapping_strategy | The rule mapping strategy. Example: mapping_strategy=auto. Possible values are: auto, custom. | Required |
| description | The correlation rule description. | Optional |
| alert_name | The alert name. | Optional |
| alert_description | The alert description. | Optional |
| alert_fields | Alert fields (string or dictionary). | Optional |
| search_window | The search window timeframe. Example: search_window=”1 hours”. | Optional |
| schedule | The correlation rule schedule. Example: schedule=”10 minutes”. | Optional |
| schedule_linux | Linux scheduling for the rule. Example: schedule_linux=”/10 ** *”. | Optional |
| suppression_enabled | Whether suppression is enabled. Possible values are: true, false. | Optional |
| suppression_duration | Duration of correlation rule suppression. | Optional |
| suppression_fields | Suppression fields. | Optional |
| dataset | The correlation rule dataset. Example: dataset=alerts. | Required |
| user_defined_severity | User-defined severity. | Optional |
| user_defined_category | User-defined category. | Optional |
| mitre_defs_json | MITRE definitions. For example: ‘{“TA0005 - Defense Evasion”: [“T1014 - Rootkit”]}’. | Optional |
| investigation_query_link | Investigation query link. | Optional |
| drilldown_query_timeframe | The drilldown query timeframe. Example: drilldown_query_timeframe=”ALERT”. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.CorrelationRule.rule_id | String | Correlation rule ID. |
xdr-correlation-rule-delete
Deletes correlation rules.
Base Command
xdr-correlation-rule-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| rule_id | Correlation rule ID. | Required |
Context Output
There is no context output for this command.
xdr-case-list
Returns a list of cases based on the specified filters.
Base Command
xdr-case-list
Input
| Argument Name | Description | Required |
|---|---|---|
| case_id | A comma-separated list of case IDs to filter by. | Optional |
| case_domain | A comma-separated list of case domains to filter by. Note: this filter is not applied when extra_data is set to true. | Optional |
| severity | A comma-separated list of severities to filter by. Note: this filter is not applied when extra_data is set to true. | Optional |
| created_before | Filters cases that were created before this date. Supports natural language expressions such as “one year”. | Optional |
| created_after | Filters cases that were created after this date. Supports natural language expressions such as “one year”. | Optional |
| status | A comma-separated list of statuses to filter by. | Optional |
| sort_field | The field by which to sort the results. Note: sorting by severity is not supported when extra_data is set to true. Possible values are: case_id, severity, creation_time. | Optional |
| sort_order | The order in which to sort the results. Possible values are: asc, desc. | Optional |
| limit | Maximum number of cases to return. | Optional |
| page_size | Page size for pagination. | Optional |
| page | Page number for pagination. | Optional |
| extra_data | Whether to retrieve extra case data including the associated issues, file artifacts, and network artifacts for each case. Possible values are: true, false. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.Case.case_id | String | The unique identifier of the case. |
| PaloAltoNetworksXDR.Case.case_name | String | The name of the case. |
| PaloAltoNetworksXDR.Case.severity | String | The severity of the case. |
| PaloAltoNetworksXDR.Case.creation_time | String | The creation time of the case. |
| PaloAltoNetworksXDR.Case.modification_time | String | The modification time of the case. |
| PaloAltoNetworksXDR.Case.status_progress | String | The progress status of the case (e.g., New, Under Investigation). |
| PaloAltoNetworksXDR.Case.description | String | A detailed description of the case and involved entities. |
| PaloAltoNetworksXDR.Case.low_severity_issue_count | Number | The number of low severity issues associated with the case. |
| PaloAltoNetworksXDR.Case.med_severity_issue_count | Number | The number of medium severity issues associated with the case. |
| PaloAltoNetworksXDR.Case.case_domain | String | The security domain of the case. |
| PaloAltoNetworksXDR.Case.xdr_url | String | The direct URL to the incident view in the XDR console. |
| PaloAltoNetworksXDR.Case.is_blocked | Boolean | Indicates if the threat was blocked. |
| PaloAltoNetworksXDR.Case.aggregated_score | Number | The overall risk score calculated for the case. |
| PaloAltoNetworksXDR.Case.host_count | Number | The number of hosts involved in the case. |
| PaloAltoNetworksXDR.Case.user_count | Number | The number of users involved in the case. |
| PaloAltoNetworksXDR.Case.wildfire_hits | Number | The number of WildFire malware hits associated with the case. |
| PaloAltoNetworksXDR.Case.tags | String | A list of tags associated with the case. |
| PaloAltoNetworksXDR.Case.starred | Boolean | Whether the case has been starred/flagged. |
| PaloAltoNetworksXDR.Case.high_severity_issue_count | Number | The number of high-severity issues associated with the case. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.critical_severity_issue_count | Number | The number of critical-severity issues associated with the case. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.resolved_timestamp | String | The time the case was resolved. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.assigned_user_mail | String | The email address of the user assigned to the case. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.assigned_user_pretty_name | String | The display name of the user assigned to the case. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.hosts | String | The hosts involved in the case. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.users | String | The users involved in the case. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.mitre_tactics_ids_and_names | String | The MITRE ATT&CK tactics associated with the case. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.mitre_techniques_ids_and_names | String | The MITRE ATT&CK techniques associated with the case. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.issue_categories | String | The categories of the issues associated with the case. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.resolve_comment | String | The comment provided when the case was resolved. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.notes | String | Notes associated with the case. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.manual_severity | String | The severity manually set for the case. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.manual_description | String | The description manually set for the case. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.rule_based_score | Number | The rule-based risk score of the case. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.predicted_score | Number | The predicted risk score of the case. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.issue_count | Number | The total number of issues associated with the case. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.issue_id | String | The unique identifier of the issue. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.case_id | String | The identifier of the case the issue belongs to. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.detection_timestamp | Number | The detection time of the issue. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.name | String | The name of the issue. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.category | String | The category of the issue. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.severity | String | The severity of the issue. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.source | String | The source of the issue. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.action | String | The action taken for the issue. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.action_pretty | String | The human-readable action taken for the issue. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.host_ip | String | The host IP addresses associated with the issue. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.host_name | String | The host name associated with the issue. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.user_name | String | The user name associated with the issue. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.action_file_name | String | The file name involved in the issue. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.action_file_path | String | The file path involved in the issue. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.mitre_tactic_id_and_name | String | The MITRE ATT&CK tactic associated with the issue. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.Issues.mitre_technique_id_and_name | String | The MITRE ATT&CK technique associated with the issue. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.FileArtifacts.case_id | String | The identifier of the case associated with the file artifact. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.FileArtifacts.type | String | The type of the file artifact. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.FileArtifacts.file_name | String | The name of the file. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.FileArtifacts.file_sha256 | String | The SHA256 hash of the file. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.FileArtifacts.file_wildfire_verdict | String | The WildFire verdict for the file. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.FileArtifacts.is_malicious | Boolean | Whether the file has been identified as malicious. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.FileArtifacts.is_process | Boolean | Whether the file was a running process. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.FileArtifacts.is_manual | Boolean | Whether the file artifact was added manually. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.FileArtifacts.file_signature_vendor_name | String | The vendor name from the file signature. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.FileArtifacts.file_signature_status | String | The status of the file digital signature. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.FileArtifacts.alert_count | Number | The number of issues associated with the file artifact. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.NetworkArtifacts.case_id | String | The identifier of the case associated with the network artifact. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.NetworkArtifacts.type | String | The type of the network artifact. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.NetworkArtifacts.network_remote_ip | String | The remote IP address associated with the network artifact. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.NetworkArtifacts.network_remote_port | Number | The remote port associated with the network artifact. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.NetworkArtifacts.network_domain | String | The domain associated with the network artifact. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.NetworkArtifacts.network_country | String | The country associated with the network artifact. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.NetworkArtifacts.alert_count | Number | The number of issues associated with the network artifact. Returned when extra_data is set to true. |
| PaloAltoNetworksXDR.Case.NetworkArtifacts.is_manual | Boolean | Whether the network artifact was added manually. Returned when extra_data is set to true. |
xdr-case-update
Updates an existing case with the specified details.
Base Command
xdr-case-update
Input
| Argument Name | Description | Required |
|---|---|---|
| case_id | The ID of the case to update. | Required |
| status | The status to set for the case. When set to “resolved”, the resolve_reason argument is required. Possible values are: new, under_investigation, resolved. | Optional |
| resolve_reason | The reason for resolving the case. Can only be provided when the status is set to “resolved”, and is required when resolving. Possible values are: resolved_known_issue, resolved_duplicate, resolved_false_positive, resolved_true_positive, resolved_security_testing, resolved_other. | Optional |
| resolve_comment | A free-text comment explaining the resolution. Can only be provided when the status is set to “resolved”. | Optional |
| user_severity | The user-defined severity to set for the case. Provide an empty string to clear the severity. Possible values are: low, medium, high, critical. | Optional |
| assigned_user | A valid Cortex XDR user email address to assign the case to. | Optional |
| notes | A free-text note for the case, used for operational or intermediate comments (e.g., a ServiceNow Ticket ID). | Optional |
| custom_fields | A JSON object string of tenant-defined custom fields to update on the case. The keys must be the exact custom field names as configured in your Cortex XDR tenant, and the values must match each field’s configuration. Ensure the custom field names are valid for the tenant; the integration only validates that the input is valid JSON. Example: {"my_custom_field": "value", "another_field": 42}. |
Optional |
Context Output
There is no context output for this command.
xdr-case-artifact-list
Retrieves a list of artifacts for a specific case.
Base Command
xdr-case-artifact-list
Input
| Argument Name | Description | Required |
|---|---|---|
| case_id | The ID of the case for which to retrieve artifacts. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.CaseNetworkArtifact.case_id | String | The ID of the case associated with the network artifact. |
| PaloAltoNetworksXDR.CaseNetworkArtifact.network_remote_ip | String | The remote IP address associated with the artifact. |
| PaloAltoNetworksXDR.CaseNetworkArtifact.network_remote_port | Number | The remote port used in the network connection. |
| PaloAltoNetworksXDR.CaseNetworkArtifact.alert_count | Number | Number of alerts associated with this network artifact. |
| PaloAltoNetworksXDR.CaseNetworkArtifact.type | String | The type of network artifact (e.g., IP). |
| PaloAltoNetworksXDR.CaseNetworkArtifact.is_manual | Boolean | Indicates if the artifact was added manually. |
| PaloAltoNetworksXDR.CaseFileArtifact.case_id | String | The ID of the case associated with the file artifact. |
| PaloAltoNetworksXDR.CaseFileArtifact.file_name | String | The name of the file. |
| PaloAltoNetworksXDR.CaseFileArtifact.file_sha256 | String | The SHA256 hash of the file. |
| PaloAltoNetworksXDR.CaseFileArtifact.file_wildfire_verdict | String | The verdict from WildFire (e.g., MALWARE, BENIGN). |
| PaloAltoNetworksXDR.CaseFileArtifact.is_malicious | Boolean | Whether the file has been identified as malicious. |
| PaloAltoNetworksXDR.CaseFileArtifact.is_process | Boolean | Indicates if the file was a running process. |
| PaloAltoNetworksXDR.CaseFileArtifact.file_signature_vendor_name | String | The vendor name from the file signature. |
| PaloAltoNetworksXDR.CaseFileArtifact.file_signature_status | String | The status of the digital signature (e.g., SIGNATURE_SIGNED). |
| PaloAltoNetworksXDR.CaseFileArtifact.alert_count | Number | Number of alerts associated with this file artifact. |
| PaloAltoNetworksXDR.CaseFileArtifact.low_confidence | Boolean | Indicates if the detection confidence is low. |
xdr-automation-playbook-create
Creates or updates an automation playbook.
Base Command
xdr-automation-playbook-create
Input
| Argument Name | Description | Required |
|---|---|---|
| entry_id | The entry ID of the file. The playbook should be a zipped YAML file. | Required |
Context Output
There is no context output for this command.
xdr-automation-playbook-get
Gets an automation playbook.
Base Command
xdr-automation-playbook-get
Input
| Argument Name | Description | Required |
|---|---|---|
| field | The field to search by. Possible values are: id, name. | Required |
| value | The field value to search for. | Required |
Context Output
There is no context output for this command.
xdr-automation-playbook-delete
Deletes an automation playbook.
Base Command
xdr-automation-playbook-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| field | The field to search by. Possible values are: id, name. | Required |
| value | The field value to search for. | Required |
Context Output
There is no context output for this command.
xdr-automation-script-delete
Deletes an automation script.
Base Command
xdr-automation-script-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| field | The field to search by. Possible values are: id, name. | Required |
| value | The field value to search for. | Required |
Context Output
There is no context output for this command.
xdr-automation-script-get
Gets an automation script.
Base Command
xdr-automation-script-get
Input
| Argument Name | Description | Required |
|---|---|---|
| field | The field to search by. Possible values are: id, name. | Required |
| value | The field value to search for. | Required |
Context Output
There is no context output for this command.
xdr-automation-script-create
Creates or updates an automation script.
Base Command
xdr-automation-script-create
Input
| Argument Name | Description | Required |
|---|---|---|
| entry_id | The entry ID of the file. The script should be a zipped YAML file. | Required |
Context Output
There is no context output for this command.
xdr-vulnerability-details-get
Gets vulnerability details by ID.
Base Command
xdr-vulnerability-details-get
Input
| Argument Name | Description | Required |
|---|---|---|
| vulnerability_id | The vulnerability ID to retrieve details for. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.Vulnerability.vulnerabilityID | String | The unique identifier (CVE ID). |
| PaloAltoNetworksXDR.Vulnerability.description | String | Detailed description of the vulnerability. |
| PaloAltoNetworksXDR.Vulnerability.publishedDate | Number | The date the vulnerability was first published. |
| PaloAltoNetworksXDR.Vulnerability.epss_score | Number | The Probability of exploitability (0-1). |
| PaloAltoNetworksXDR.Vulnerability.exploitDetails.exploitMaturity | String | Current state of exploit availability (e.g., weaponized). |
| PaloAltoNetworksXDR.Vulnerability.exploitDetails.weaponizedExploitFound | Boolean | Whether a functional exploit exists in the wild. |
| PaloAltoNetworksXDR.Vulnerability.exploitDetails.reportedExploited | Boolean | Whether the vulnerability has been actively exploited. |
| PaloAltoNetworksXDR.Vulnerability.exploitDetails.reportedExploitedByThreatActors | Boolean | Whether known threat actors are exploiting this vulnerability. |
| PaloAltoNetworksXDR.Vulnerability.exploitDetails.reportedExploitedByRansomware | Boolean | Whether the vulnerability is used in ransomware campaigns. |
| PaloAltoNetworksXDR.Vulnerability.exploitDetails.reportedExploitedByBotnets | Boolean | Whether the vulnerability is being leveraged by botnet clusters. |
| PaloAltoNetworksXDR.Vulnerability.exploitDetails.firstReportedThreatActor | Number | The timestamp of the first recorded threat actor activity. |
| PaloAltoNetworksXDR.Vulnerability.exploitDetails.mostRecentReportedThreatActor | Number | The timestamp of the last recorded threat actor activity. |
| PaloAltoNetworksXDR.Vulnerability.cisaKevDateDue | Number | The deadline set by CISA for federal agency remediation. |
| PaloAltoNetworksXDR.Vulnerability.weaknesses.cweId | String | The Common Weakness Enumeration ID. |
| PaloAltoNetworksXDR.Vulnerability.vulncheck-threat-actors | String | A list of specific threat actor groups associated with the vulnerability. |
xdr-healthcheck-run
Runs a system health check on the Cortex XDR environment.
Base Command
xdr-healthcheck-run
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.HealthStatus.status | String | The health status of the Cortex XDR system. |
xdr-endpoint-triage-preset-list
Gets a list of available triage presets.
Base Command
xdr-endpoint-triage-preset-list
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.EndpointTriagePreset.created_by | String | The user or system entity that created the triage preset. |
| PaloAltoNetworksXDR.EndpointTriagePreset.description | String | A brief explanation of the preset’s purpose or contents. |
| PaloAltoNetworksXDR.EndpointTriagePreset.name | String | The unique display name of the triage preset. |
| PaloAltoNetworksXDR.EndpointTriagePreset.os | String | The operating system platform the preset targets (e.g., windows, linux, macos). |
| PaloAltoNetworksXDR.EndpointTriagePreset.type | String | The category or classification of the preset (e.g., standard, custom). |
| PaloAltoNetworksXDR.EndpointTriagePreset.uuid | String | The unique universal identifier (UUID) assigned to this specific preset. |
xdr-endpoint-triage
Initiates a forensics triage on the specified endpoints. You must have Cortex XDR with the Forensics add-on. The agent also must have the Forensics License enabled.
Base Command
xdr-endpoint-triage
Input
| Argument Name | Description | Required |
|---|---|---|
| endpoint_id | A comma-separated list of endpoint IDs to initiate triage on. You can find the endpoint ID under the “Inventory” section, under “All Endpoints”. | Required |
| collector_uuid | The collector UUID to use for the triage. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.EndpointTriage.TRIAGE_ID | String | The unique identifier assigned to the created triage action. |
| PaloAltoNetworksXDR.EndpointTriage.SUCCESSFUL_AGENT_IDS | Array | A list of agent IDs where the triage action was successfully initiated. |
| PaloAltoNetworksXDR.EndpointTriage.UNSUCCESSFUL_AGENT_IDS | Array | A list of agent IDs where the triage action failed to initiate. |
xdr-issue-list
Retrieve issues based on filters. Issues with an ‘INFO’ severity level are filtered out.
Base Command
xdr-issue-list
Input
| Argument Name | Description | Required |
|---|---|---|
| issue_id | A comma-separated list of issue IDs. | Optional |
| external_id | A comma-separated list of external IDs. | Optional |
| detection_method | A comma-separated list of methods used to detect the activity. Possible values: ‘BIOC’, ‘Correlation’, ‘Analytics’, ‘System’, ‘IOC’. Possible values are: BIOC, Correlation, Analytics, System, IOC. | Optional |
| domain | A comma-separated list of domains. | Optional |
| severity | A comma-separated list of severities. Possible values: ‘critical’, ‘high’, ‘medium’, ‘low’, ‘info’. Possible values are: info, low, medium, high, critical. | Optional |
| insert_time | Filter by issues inserted after this time. | Optional |
| status | A comma-separated list of statuses. Possible values: ‘New’, ‘In Progress’, ‘Resolved’. Possible values are: New, In Progress, Resolved. | Optional |
| sort_field | The field to sort by. Possible values are: issue_id, severity, observation_time. | Optional |
| sort_order | The sort order. Possible values are: asc, desc. | Optional |
| limit | The maximum number of results to return. | Optional |
| page_size | The page size. | Optional |
| page | The page number. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.Issue.observation_time | Number | The timestamp when the observation occurred. |
| PaloAltoNetworksXDR.Issue.domain | String | The security domain associated with the observation. |
| PaloAltoNetworksXDR.Issue.remediation | String | Suggested remediation steps. |
| PaloAltoNetworksXDR.Issue.impact | String | The potential impact of the observed activity. |
| PaloAltoNetworksXDR.Issue.status | String | The current progress status (e.g., New). |
| PaloAltoNetworksXDR.Issue.status_resolution_comment | String | Comments regarding the resolution of the status. |
| PaloAltoNetworksXDR.Issue.status_progress | String | The current progress status (e.g., New). |
| PaloAltoNetworksXDR.Issue.asset_ids | String | List of asset IDs involved. |
| PaloAltoNetworksXDR.Issue.assigned_to_pretty | String | The display name of the user assigned to this item. |
| PaloAltoNetworksXDR.Issue.last_update_timestamp | Number | The last time this record was updated. |
| PaloAltoNetworksXDR.Issue.detection_method | String | The method used to detect the activity (e.g., BIOC). |
| PaloAltoNetworksXDR.Issue.is_starred | Boolean | Whether the item has been starred/flagged. |
| PaloAltoNetworksXDR.Issue.name | String | The name of the observation or alert. |
| PaloAltoNetworksXDR.Issue.external_id | String | The unique UUID for external reference. |
| PaloAltoNetworksXDR.Issue.insert_time | Number | The time the record was inserted into the database. |
| PaloAltoNetworksXDR.Issue.detection_rule_id | String | The ID of the specific detection rule triggered. |
| PaloAltoNetworksXDR.Issue.tags | String | A list of tags associated with the observation. |
| PaloAltoNetworksXDR.Issue.type | String | The classification type of the observation. |
| PaloAltoNetworksXDR.Issue.id | Number | The numeric ID of the observation. |
| PaloAltoNetworksXDR.Issue.description | String | Detailed description of the observed activity. |
| PaloAltoNetworksXDR.Issue.severity | String | The severity level (e.g., LOW). |
| PaloAltoNetworksXDR.Issue.category | String | The category classification. |
| PaloAltoNetworksXDR.Issue.is_excluded | Boolean | Whether this observation is excluded from standard views. |
xdr-issue-create
Creates a new issue. Issues with an ‘INFO’ severity level are not displayed in the UI.
Base Command
xdr-issue-create
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The issue name. | Required |
| description | The issue description. | Required |
| observation_time | The observation time. Should support english expressions like “one year”. | Required |
| domain | The domain. | Required |
| category | The category. | Required |
| asset_id | A comma-separated list of asset IDs. | Optional |
| mitre_tactic | A comma-separated list of MITRE tactics. | Optional |
| mitre_technique | A comma-separated list of MITRE techniques. | Optional |
| type | The issue type. | Optional |
| extended_description | The extended description. | Optional |
| impact | The impact. | Optional |
| tags | A comma-separated list of tags. | Optional |
| is_excluded | Whether the issue is excluded. Possible values are: true, false. | Optional |
| is_starred | Whether the issue is starred. Possible values are: true, false. | Optional |
| assigned_to | The user assigned to the issue. | Optional |
| assigned_to_pretty | The pretty name of the user assigned to the issue. | Optional |
| severity | The severity. Possible values are: critical, info, low, medium, high. | Required |
| normalized_fields_json | The JSON to add to the “normalized_fields” field in the API. | Optional |
| custom_fields_json | The JSON to add to the “custom_fields” field in the API. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.Issue.external_id | String | The issue external ID. |
| PaloAltoNetworksXDR.Issue.detection_method | String | The issue detection method. |
xdr-issue-update
Updates an existing issue.
Base Command
xdr-issue-update
Input
| Argument Name | Description | Required |
|---|---|---|
| issue_id | The issue ID. | Required |
| severity | The severity. Possible values are: critical, info, low, medium, high. | Optional |
| status | The status. Possible values are: new, in_progress, resolved. | Optional |
| resolve_reason | The resolve reason. Possible values are: resolved_threat_handled, resolved_known_issue, resolved_duplicate, resolved_false_positive, resolved_other, resolved_true_positive, resolved_security_testing. | Optional |
| resolve_comment | The resolve comment. | Optional |
Context Output
There is no context output for this command.
Configuration parameters
isFetch— Fetch incidentsincidentFetchInterval— Incidents Fetch IntervalincidentType— Incident typeurl— Server URL (copy URL from XDR) (required)apikey_id_creds—apikey_creds—dont_format_sublists— Remove legacy incident fieldsmirror_direction— Incident Mirroring Directionclose_xsoar_incident— Close Mirrored XSOAR Incidentclose_xdr_incident— Close Mirrored Cortex XDR Incidentxdr_delay— XDR mirroring delay in minutescustom_xsoar_to_xdr_close_reason_mapping— Custom close-reason mapping (XSOAR -> XDR mirrored incident. Overwrites default close-reason mapping defined by Cortex XSOAR)custom_xdr_to_xsoar_close_reason_mapping— Custom close-reason mapping (XDR -> XSOAR mirrored incident. Overwrites default close-reason mapping defined by Cortex XSOAR)apikey_id— API Key IDapikey— API Keytimeout— HTTP Timeoutmax_fetch— Maximum number of incidents per fetchstarred— Only fetch starred incidentsstarred_incidents_fetch_window— Starred incidents fetch windowfetch_time— First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days)sync_owners— Sync Incident Ownersinsecure— Trust any certificate (not secure)proxy— Use system proxy settingsprevent_only— Prevent Only Modestatus— Incident Statuses to Fetchexclude_fields— Minimize Incident Informationexcluded_alert_fields— Minimize Alert Informationclose_alerts_in_xdr— Close all related alerts in XDR
Commands (109)
-
endpointReturns information about an endpoint.
-
get-mapping-fieldsGets mapping fields from remote incident. Note: This method will not update the current incident. It's here for debugging purposes.
-
get-modified-remote-dataGets the list of incidents that were modified since the last update. Note: This method is here for debugging purposes. get-modified-remote-data is used as part of a Mirroring feature, which is available since version 6.1.
-
get-remote-dataGets remote data from a remote incident. Note: This method will not update the current incident. It's here for debugging purposes.
-
xdr-action-status-getRetrieves the status of the requested actions according to the action ID.
-
xdr-allowlist-filesAdds requested files to the allow list if they are not already on the block list or allow list.
-
xdr-api-key-deleteDeletes the specified API keys.
-
xdr-api-key-listGets a list of existing API keys.
-
xdr-asset-group-createCreates an asset group.
-
xdr-asset-group-deleteDeletes an asset group.
-
xdr-asset-group-listReturns a list of asset groups.
-
xdr-asset-group-updateUpdates an asset group.
-
xdr-asset-listReturns a list of assets.
-
xdr-asset-schema-field-options-getGets the enum values of a specified field in the asset schema.
-
xdr-asset-schema-getGets the schema of the asset inventory.
-
xdr-automation-playbook-createCreates or updates an automation playbook.
-
xdr-automation-playbook-deleteDeletes an automation playbook.
-
xdr-automation-playbook-getGets an automation playbook.
-
xdr-automation-script-createCreates or updates an automation script.
-
xdr-automation-script-deleteDeletes an automation script.
-
xdr-automation-script-getGets an automation script.
-
xdr-bioc-createCreates a new BIOC.
-
xdr-bioc-deleteDeletes a BIOC.
-
xdr-bioc-listReturns a list of BIOCs.
-
xdr-bioc-updateUpdates an existing BIOC.
-
xdr-blacklist-filesDeprecatedDeprecated. Use `xdr-blocklist-files` instead.
-
xdr-blocklist-filesBlock lists requested files which have not already been block listed or added to allow lists.
-
xdr-case-artifact-listRetrieves a list of artifacts for a specific case.
-
xdr-case-listReturns a list of cases based on the specified filters.
-
xdr-case-updateUpdates an existing case with the specified details.
-
xdr-correlation-rule-createCreates a new correlation rule.
-
xdr-correlation-rule-deleteDeletes correlation rules.
-
xdr-correlation-rule-listReturns a list of correlation rules.
-
xdr-correlation-rule-updateUpdates an existing correlation rule.
-
xdr-create-distributionCreates an installation package. This is an asynchronous call that returns the distribution ID. This does not mean that the creation succeeded. To confirm that the package has been created, check the status of the distribution by running the Get Distribution Status API.
-
xdr-delete-endpointsDeletes selected endpoints in the Cortex XDR app. You can delete up to 1000 endpoints.
-
xdr-endpoint-alias-changeGets a list of endpoints according to the passed filters, and changes their alias name. Filtering by multiple fields will be concatenated using the AND condition (OR is not supported).
-
xdr-endpoint-isolateIsolates the specified endpoint.
-
xdr-endpoint-scanDeprecatedDeprecated. Use `xdr-endpoint-scan-execute` instead.
-
xdr-endpoint-scan-abortCancels the scan of selected endpoints. A scan can only be aborted if the selected endpoints are Pending or In Progress. To scan all endpoints, run the command with the argument all=true. Note that scanning all of the endpoints may cause performance issues and latency.
-
xdr-endpoint-scan-executeRuns a scan on a selected endpoint. To scan all endpoints, run this command with argument all=true. Note: Scanning all the endpoints may cause performance issues and latency.
-
xdr-endpoint-tag-addAdds a tag to specified endpoint_ids.
-
xdr-endpoint-tag-removeRemoves a tag from specified endpoint_ids.
-
xdr-endpoint-triageInitiates a forensics triage on the specified endpoints. You must have Cortex XDR with the Forensics add-on. The agent also must have the Forensics License enabled.
-
xdr-endpoint-triage-preset-listGets a list of available triage presets.
-
xdr-endpoint-unisolateReverses the isolation of an endpoint.
-
xdr-file-delete-script-executeInitiates a new endpoint script execution to delete the specified file.
-
xdr-file-exist-script-executeInitiates a new endpoint script execution to check if the file exists.
-
xdr-file-quarantineQuarantines a file on selected endpoints. You can select up to 1000 endpoints.
-
xdr-file-restoreRestores a quarantined file on requested endpoints.
-
xdr-file-retrieveRetrieves files from selected endpoints. You can retrieve up to 20 files, from no more than 10 endpoints. At least one endpoint ID and one file path are necessary in order to run the command. After running this command, you can use the xdr-action-status-get command with returned action_id, to check the action status.
-
xdr-get-alertsDeprecatedThis command is deprecated, please use xdr-issue-list instead. Returns a list of alerts and their metadata, which you can filter by built-in arguments or use the custom_filter to input a JSON filter object. Multiple filter arguments will be concatenated using the AND operator, while arguments that support a comma-separated list of values will use an OR operator between each value.
-
xdr-get-audit-agent-reportsGets agent event reports. You can filter by multiple fields, which will be concatenated using the AND condition (OR is not supported). Maximum result set size is 100. Offset is the zero-based number of reports from the start of the result set (start by counting from 0).
-
xdr-get-audit-management-logsGets management logs. You can filter by multiple fields, which will be concatenated using the AND condition (OR is not supported). Maximum result set size is 100. Offset is the zero-based number of management logs from the start of the result set (start by counting from 0).
-
xdr-get-cloud-original-alertsDeprecatedThis command is deprecated. Returns information about each alert ID.
-
xdr-get-contributing-eventRetrieves contributing events for a specific correlation alert.
-
xdr-get-create-distribution-statusGets the status of the installation package.
-
xdr-get-distribution-urlGets the distribution URL for downloading the installation package.
-
xdr-get-distribution-versionsGets a list of all the agent versions to use for creating a distribution list.
-
xdr-get-endpoint-device-control-violationsGets a list of device control violations filtered by selected fields. You can retrieve up to 100 violations.
-
xdr-get-endpointsGets a list of endpoints, according to the passed filters. If there are no filters, all endpoints are returned. Filtering by multiple fields will be concatenated using AND condition (OR is not supported). Maximum result set size is 100. Offset is the zero-based number of endpoint from the start of the result set. (Start by counting from 0).
-
xdr-get-endpoints-by-statusReturns the number of the connected\disconnected endpoints.
-
xdr-get-incident-extra-dataDeprecatedThis command is deprecated. Use "xdr-case-list extra_data=true" instead. Returns additional data for the specified incident, for example, related alerts, file artifacts, network artifacts, and so on.
-
xdr-get-incidentsDeprecatedThis command is deprecated please use xdr-case-list instead. Returns a list of incidents, which you can filter by a list of incident IDs (max. 100), the time the incident was last modified, and the time the incident was created. If you pass multiple filtering arguments, they will be concatenated using the AND condition. The OR condition is not supported.
-
xdr-get-policyGets the policy name for a specific endpoint.
-
xdr-get-quarantine-statusRetrieves the quarantine status for a selected file.
-
xdr-get-script-codeGets the code of a specific script in the script library.
-
xdr-get-script-execution-result-filesGets the files retrieved from a specific endpoint during a script execution.
-
xdr-get-script-execution-resultsRetrieve the results of a script execution action.
-
xdr-get-script-execution-statusRetrieves the status of a script execution action.
-
xdr-get-script-metadataGets the full definition of a specific script in the scripts library.
-
xdr-get-scriptsGets a list of scripts available in the scripts library.
-
xdr-get-tenant-infoProvides information about the tenant.
-
xdr-healthcheck-runRuns a system health check on the Cortex XDR environment.
-
xdr-insert-cef-alertsDeprecatedThis command is deprecated. Upload alerts in CEF format from external alert sources. After you map CEF alert fields to Cortex XDR fields, Cortex XDR displays the alerts in related incidents and views. You can send 600 requests per minute. Each request can contain a maximum of 60 alerts.
-
xdr-insert-parsed-alertDeprecatedThis command is deprecated. Uploads an alert from external alert sources in Cortex XDR format. Cortex XDR displays alerts that are parsed successfully in related incidents and views. You can send 600 alerts per minute. Each request can contain a maximum of 60 alerts.
-
xdr-isolate-endpointDeprecatedDeprecated. Use `xdr-endpoint-isolate` instead.
-
xdr-issue-createCreates a new issue. Issues with an 'INFO' severity level are not displayed in the UI.
-
xdr-issue-listRetrieve issues based on filters. Issues with an 'INFO' severity level are filtered out.
-
xdr-issue-updateUpdates an existing issue.
-
xdr-kill-process-script-executeInitiates a new endpoint script execution kill process.
-
xdr-list-risky-hostsRetrieve the risk score of a specific host or list of hosts with the highest risk score in the environment along with the reason affecting each score.
-
xdr-list-risky-usersRetrieve the risk score of a specific user or list of users with the highest risk score in the environment along with the reason affecting each score.
-
xdr-list-rolesRetrieve information about one or more roles created in the environment.
-
xdr-list-user-groupsRetrieve a list of the current user emails associated with one or more user groups in the environment.
-
xdr-list-usersRetrieve a list of the current users in the environment.
-
xdr-quarantine-filesDeprecatedDeprecated. Use `xdr-file-quarantine` instead.
-
xdr-remove-allowlist-filesRemoves requested files from allow list.
-
xdr-remove-blocklist-filesRemoves requested files from the block list.
-
xdr-remove-user-roleRemove one or more users from a role.
-
xdr-replace-featured-fieldReplace the featured hosts\users\IP addresses\active directory groups listed in your environment.
-
xdr-restore-fileDeprecatedDeprecated. Use `xdr-file-restore` instead.
-
xdr-retrieve-file-detailsView the file retrieved by the xdr-retrieve-files command according to the action ID. Before running this command, you can use the xdr-action-status-get command to check if this action completed successfully.
-
xdr-retrieve-filesDeprecatedDeprecated. Use `xdr-file-retrieve` instead.
-
xdr-run-scriptDeprecatedDeprecated. Run xdr-script-run instead.
-
xdr-run-script-delete-fileDeprecatedDeprecated. Use `xdr-file-delete-script-execute` instead.
-
xdr-run-script-execute-commandsDeprecatedDeprecated. Use `xdr-script-commands-execute` instead.
-
xdr-run-script-file-existsDeprecatedDeprecated. Use `xdr-file-exist-script-execute` instead.
-
xdr-run-script-kill-processDeprecatedDeprecated. Use `xdr-kill-process-script-execute` instead.
-
xdr-run-snippet-code-scriptDeprecatedDeprecated. Use `xdr-snippet-code-script-execute` instead.
-
xdr-script-commands-executeInitiates a new endpoint script execution of shell commands.
-
xdr-script-runInitiates a new endpoint script execution action using a script from the script library and returns the results.
-
xdr-set-user-roleAdd one or more users to a role.
-
xdr-snippet-code-script-executeInitiates a new endpoint script execution action using the provided snippet code.
-
xdr-unisolate-endpointDeprecatedDeprecated. Use `xdr-endpoint-unisolate` instead.
-
xdr-update-alertDeprecatedThis command is deprecated, please use xdr-issue-update instead. Update one or more alerts with the provided arguments. Required license: Cortex XDR Prevent, Cortex XDR Pro per Endpoint, or Cortex XDR Pro per GB.
-
xdr-update-incidentDeprecatedThis command is deprecated please use xdr-case-update instead. Updates one or more fields of a specified incident. Missing fields will be ignored. To remove the assignment for an incident, pass a null value in the assignee email argument.
-
xdr-vulnerability-details-getGets vulnerability details by ID.
-
xdr-whitelist-filesDeprecatedDeprecated. Use `xdr-allowlist-files` instead.
import hashlib import secrets import string from datetime import datetime, timedelta from itertools import zip_longest import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 from CoreIRApiModule import * FORWARD_USER_RUN_RBAC = False TIME_FORMAT = "%Y-%m-%dT%H:%M:%S" NONCE_LENGTH = 64 API_KEY_LENGTH = 128 INTEGRATION_CONTEXT_BRAND = "PaloAltoNetworksXDR" XDR_INCIDENT_TYPE_NAME = "Cortex XDR Incident Schema" INTEGRATION_NAME = "Cortex XDR - IR" ALERTS_LIMIT_PER_INCIDENTS: int = -1 REMOVE_ALERTS_NULL_VALUES = "null_values" FIELDS_TO_EXCLUDE = ["network_artifacts", "file_artifacts"] XDR_INCIDENT_FIELDS = { "status": { "description": 'Current status of the incident: "new","under_' 'investigation","resolved_known_issue",' '"resolved_duplicate","resolved_false_positive",' '"resolved_true_positive","resolved_security_testing","resolved_other"', "xsoar_field_name": "xdrstatusv2", }, "assigned_user_mail": {"description": "Email address of the assigned user.", "xsoar_field_name": "xdrassigneduseremail"}, "assigned_user_pretty_name": { "description": "Full name of the user assigned to the incident.", "xsoar_field_name": "xdrassigneduserprettyname", }, "resolve_comment": { "description": "Comments entered by the user when the incident was resolved.", "xsoar_field_name": "xdrresolvecomment", }, "manual_severity": { "description": "Incident severity assigned by the user. This does not affect the calculated severity low medium high", "xsoar_field_name": "severity", }, "close_reason": {"description": "The close reason of the XSOAR incident", "xsoar_field_name": "closeReason"}, } MIRROR_DIRECTION = {"None": None, "Incoming": "In", "Outgoing": "Out", "Both": "Both"} XSOAR_TO_XDR = "XSOAR -> XDR" XDR_TO_XSOAR = "XDR -> XSOAR" XDR_OPEN_STATUS_TO_XSOAR = ["under_investigation", "new"] BIOC_AND_CR_SEVERITY_MAPPING = { "info": "SEV_010_INFO", "low": "SEV_020_LOW", "medium": "SEV_030_MEDIUM", "high": "SEV_040_HIGH", "critical": "SEV_050_CRITICAL", } ISSUE_STATUSES_MAP = {"new": "New", "in_progress": "In Progress", "resolved": "Resolved"} ISSUE_REASON_MAP = { "resolved_threat_handled": "resolved - threat handled", "resolved_known_issue": "resolved - known issue", "resolved_duplicate": "resolved - duplicate issue", "resolved_false_positive": "resolved - false positive", "resolved_other": "resolved - other", "resolved_true_positive": "resolved - true positive", "resolved_security_testing": "resolved - security testing", } INCIDENT_TO_CASE_FIELD_MAP = { "incident_id": "case_id", "incident_name": "case_name", "status": "status_progress", "incident_domain": "case_domain", "alert_count": "issue_count", "low_severity_alert_count": "low_severity_issue_count", "med_severity_alert_count": "med_severity_issue_count", "high_severity_alert_count": "high_severity_issue_count", "critical_severity_alert_count": "critical_severity_issue_count", "alert_categories": "issue_categories", } def convert_epoch_to_milli(timestamp): if timestamp is None: return None if 9 < len(str(timestamp)) < 13: timestamp = int(timestamp) * 1000 return int(timestamp) def convert_datetime_to_epoch(the_time: (int | datetime) = 0): if the_time is None: return None try: if isinstance(the_time, datetime): return int(the_time.strftime("%s")) except Exception as err: demisto.debug(err) return 0 def convert_datetime_to_epoch_millis(the_time: (int | datetime) = 0): return convert_epoch_to_milli(convert_datetime_to_epoch(the_time=the_time)) def generate_current_epoch_utc(): return convert_datetime_to_epoch_millis(datetime.now(timezone.utc)) def generate_key(): return "".join([secrets.choice(string.ascii_letters + string.digits) for _ in range(API_KEY_LENGTH)]) def create_auth(api_key): nonce = "".join([secrets.choice(string.ascii_letters + string.digits) for _ in range(NONCE_LENGTH)]) timestamp = str(generate_current_epoch_utc()) # Get epoch time utc millis hash_ = hashlib.sha256() hash_.update((api_key + nonce + timestamp).encode("utf-8")) return nonce, timestamp, hash_.hexdigest() def clear_trailing_whitespace(res): index = 0 while index < len(res): for key, value in res[index].items(): if isinstance(value, str): res[index][key] = value.rstrip() index += 1 return res def replace_dots_in_keys(data: Any) -> Any: """ Recursively replaces dots with underscores in dictionary keys. Args: data (Any): The input data structure (dictionary, list, or primitive) to process. Returns: Any: The data structure with all dictionary keys having dots replaced by underscores. """ if isinstance(data, dict): return {k.replace(".", "_"): replace_dots_in_keys(v) for k, v in data.items()} elif isinstance(data, list): return [replace_dots_in_keys(i) for i in data] return data def filter_and_save_unseen_incident(incidents: List, limit: int, number_of_already_filtered_incidents: int) -> List: """ Filters incidents that were seen already and saves the unseen incidents to LastRun object. :param incidents: List of incident - must be list :param limit: the maximum number of incident per fetch :param number_of_already_filtered_incidents: number of incidents that were fetched already :return: the filtered incidents. """ last_run_obj = demisto.getLastRun() fetched_starred_incidents = last_run_obj.pop("fetched_starred_incidents", {}) filtered_incidents = [] for incident in incidents: incident_id = incident.get("incident_id") if incident_id in fetched_starred_incidents: demisto.debug(f"incident (ID {incident_id}) was already fetched in the past.") continue fetched_starred_incidents[incident_id] = True filtered_incidents.append(incident) number_of_already_filtered_incidents += 1 if number_of_already_filtered_incidents >= limit: break last_run_obj["fetched_starred_incidents"] = fetched_starred_incidents demisto.setLastRun(last_run_obj) return filtered_incidents def get_xsoar_close_reasons(): """ Get the default XSOAR close-reasons in addition to custom close-reasons from server configuration. """ default_xsoar_close_reasons = list(XSOAR_RESOLVED_STATUS_TO_XDR.keys()) custom_close_reasons: List[str] = [] try: server_config = get_server_config() demisto.debug(f"get_xsoar_close_reasons server-config: {server_config!s}") if server_config: custom_close_reasons = argToList(server_config.get("incident.closereasons", "")) except Exception as e: demisto.error(f"Could not get server configuration: {e}") return default_xsoar_close_reasons + custom_close_reasons def validate_custom_close_reasons_mapping(mapping: str, direction: str): """Check validity of provided custom close-reason mappings.""" xdr_statuses = [status.replace("resolved_", "").replace("_", " ").title() for status in XDR_RESOLVED_STATUS_TO_XSOAR] xsoar_statuses = get_xsoar_close_reasons() exception_message = ( 'Improper custom mapping ({direction}) provided: "{key_or_value}" is not a valid Cortex ' "{xsoar_or_xdr} close-reason. Valid Cortex {xsoar_or_xdr} close-reasons are: {statuses}" ) def to_xdr_status(status): return "resolved_" + "_".join(status.lower().split(" ")) custom_mapping = comma_separated_mapping_to_dict(mapping) valid_key = valid_value = True # If no mapping was provided. for key, value in custom_mapping.items(): if direction == XSOAR_TO_XDR: xdr_close_reason = to_xdr_status(value) valid_key = key in xsoar_statuses valid_value = xdr_close_reason in XDR_RESOLVED_STATUS_TO_XSOAR elif direction == XDR_TO_XSOAR: xdr_close_reason = to_xdr_status(key) valid_key = xdr_close_reason in XDR_RESOLVED_STATUS_TO_XSOAR valid_value = value in xsoar_statuses if not valid_key: raise DemistoException( exception_message.format( direction=direction, key_or_value=key, xsoar_or_xdr="XSOAR" if direction == XSOAR_TO_XDR else "XDR", statuses=xsoar_statuses if direction == XSOAR_TO_XDR else xdr_statuses, ) ) elif not valid_value: raise DemistoException( exception_message.format( direction=direction, key_or_value=value, xsoar_or_xdr="XDR" if direction == XSOAR_TO_XDR else "XSOAR", statuses=xdr_statuses if direction == XSOAR_TO_XDR else xsoar_statuses, ) ) def handle_excluded_data_from_alerts_param(excluded_alert_fields: list = []) -> tuple[list, bool]: """handles the excluded_alert_fields parameter Args: excluded_alert_fields (list, optional): the fields from alerts to exclude. Defaults to []. Returns: (list, bool): (Which fields of alerts should be excluded from the response, and whether null values should be excluded from the response) """ remove_nulls_from_alerts = REMOVE_ALERTS_NULL_VALUES in excluded_alert_fields demisto.debug(f"handle_excluded_data_from_alerts_param {remove_nulls_from_alerts=}, {excluded_alert_fields=}") formatted_excluded_data = [field for field in excluded_alert_fields if field != REMOVE_ALERTS_NULL_VALUES] return formatted_excluded_data, remove_nulls_from_alerts class Client(CoreClient): def __init__(self, base_url, proxy, verify, timeout, params=None): if not params: params = {} self._params = params super().__init__(base_url=base_url, proxy=proxy, verify=verify, headers=self.headers, timeout=timeout) @property def headers(self): return get_headers(self._params) def test_module(self, first_fetch_time): """ Performs basic get request to get item samples """ last_one_day, _ = parse_date_range(first_fetch_time, TIME_FORMAT) try: self.get_incidents(lte_creation_time=last_one_day, limit=1) except Exception as err: if "API request Unauthorized" in str(err): # this error is received from the XDR server when the client clock is not in sync to the server raise DemistoException(f"{err!s} please validate that your both XSOAR and XDR server clocks are in sync") else: raise # XSOAR -> XDR validate_custom_close_reasons_mapping( mapping=self._params.get("custom_xsoar_to_xdr_close_reason_mapping"), direction=XSOAR_TO_XDR ) # XDR -> XSOAR validate_custom_close_reasons_mapping( mapping=self._params.get("custom_xdr_to_xsoar_close_reason_mapping"), direction=XDR_TO_XSOAR ) def handle_fetch_starred_incidents(self, limit: int, page_number: int, request_data: dict) -> List: """ handles pagination and filter of starred incidents that were fetched. :param limit: the maximum number of incident per fetch :param page_number: page number :param request_data: the api call request data :return: the filtered starred incidents. """ res = self._http_request( method="POST", url_suffix="/incidents/get_incidents/", json_data={"request_data": request_data}, headers=self.headers, timeout=self.timeout, ) raw_incidents = res.get("reply", {}).get("incidents", []) # we want to avoid duplications of starred incidents in the fetch-incident command (we fetch all incidents # in the fetch window). filtered_incidents = filter_and_save_unseen_incident(raw_incidents, limit, 0) # we want to support pagination on starred incidents. while len(filtered_incidents) < limit: page_number += 1 search_from = page_number * limit search_to = search_from + limit request_data["search_from"] = search_from request_data["search_to"] = search_to res = self._http_request( method="POST", url_suffix="/incidents/get_incidents/", json_data={"request_data": request_data}, headers=self.headers, timeout=self.timeout, ) raw_incidents = res.get("reply", {}).get("incidents", []) if not raw_incidents: break filtered_incidents += filter_and_save_unseen_incident(raw_incidents, limit, len(filtered_incidents)) return filtered_incidents def update_incident( self, incident_id, status=None, assigned_user_mail=None, severity=None, resolve_comment=None, unassign_user=None, add_comment=None, ): update_data: dict[str, Any] = {} if unassign_user and assigned_user_mail: raise ValueError("Can't provide both assignee_email/assignee_name and unassign_user") if unassign_user: update_data["assigned_user_mail"] = "none" if assigned_user_mail: update_data["assigned_user_mail"] = assigned_user_mail if status: update_data["status"] = status if severity: update_data["manual_severity"] = severity if resolve_comment: update_data["resolve_comment"] = resolve_comment if add_comment: update_data["comment"] = {"comment_action": "add", "value": add_comment} request_data = { "incident_id": incident_id, "update_data": update_data, } self._http_request( method="POST", url_suffix="/incidents/update_incident/", json_data={"request_data": request_data}, headers=self.headers, timeout=self.timeout, ) def get_incident_extra_data( self, incident_id, alerts_limit=1000, exclude_artifacts: bool = False, excluded_alert_fields: List = [], remove_nulls_from_alerts: bool = False, ): """ Returns incident by id :param incident_id: The id of incident :param alerts_limit: Maximum number alerts to get :return: """ request_data = {"incident_id": incident_id, "alerts_limit": alerts_limit, "full_alert_fields": True} if excluded_alert_fields: request_data["alert_fields_to_exclude"] = excluded_alert_fields if remove_nulls_from_alerts: request_data["drop_nulls"] = True reply = self._http_request( method="POST", url_suffix="/incidents/get_incident_extra_data/", json_data={"request_data": request_data}, headers=self.headers, timeout=self.timeout, ) incident = reply.get("reply") set_sorted_paths_and_names(incident) # workaround for excluding fields which is not supported with the get_incident_extra_data endpoint if exclude_artifacts: for field in FIELDS_TO_EXCLUDE: incident.pop(field, None) return incident def save_modified_incidents_to_integration_context(self): last_modified_incidents = self.get_incidents(limit=100, sort_by_modification_time="desc") modified_incidents_context = {} for incident in last_modified_incidents: incident_id = incident.get("incident_id") modified_incidents_context[incident_id] = incident.get("modification_time") set_integration_context({"modified_incidents": modified_incidents_context}) def get_contributing_event_by_alert_id(self, alert_id: int) -> dict: request_data = { "request_data": { "alert_id": alert_id, } } reply = self._http_request( method="POST", url_suffix="/alerts/get_correlation_alert_data/", json_data=request_data, headers=self.headers, timeout=self.timeout, ) return reply.get("reply", {}) def replace_featured_field(self, field_type: str, fields: list[dict]) -> dict: request_data = {"request_data": {"fields": fields}} reply = self._http_request( method="POST", url_suffix=f"/featured_fields/replace_{field_type}", json_data=request_data, timeout=self.timeout, headers=self.headers, raise_on_status=True, ) return reply.get("reply") def get_api_keys(self, request_data: dict): """ Gets a list of existing API keys. Args: request_data (dict): The request data Returns: list: A list of API keys. """ res = self._http_request( method="POST", url_suffix="/api_keys/get_api_keys/", json_data={"request_data": request_data}, headers=self.headers, timeout=self.timeout, ) return res.get("reply", {}).get("DATA", []) def delete_api_keys(self, request_data: dict): """ Deletes the specified API keys. Args: request_data (dict): List of API key IDs to delete. Returns: dict: The API response. """ return self._http_request( method="POST", url_suffix="/api_keys/delete/", json_data={"request_data": request_data}, headers=self.headers, timeout=self.timeout, ) def get_tenant_info(self): reply = self._http_request( method="POST", url_suffix="/system/get_tenant_info/", json_data={"request_data": {}}, headers=self.headers, timeout=self.timeout, ) return reply.get("reply", {}) def get_multiple_incidents_extra_data( self, exclude_artifacts, incident_id_list=[], gte_creation_time_milliseconds=0, lte_creation_time_milliseconds=0, statuses=[], starred=None, starred_incidents_fetch_window=None, page_number=0, limit=100, search_from=0, sort_field=None, sort_order=None, excluded_alert_fields=[], remove_nulls_from_alerts=False, ): """ Returns incident by id :param incident_id_list: The list ids of incidents :param lte_creation_time_milliseconds: Filters incidents created before this timestamp (in milliseconds). :param search_from: The starting offset for pagination (maps to the search_from field). :param sort_field: The field by which to sort the results (creation_time, modification_time, incident_id). :param sort_order: The sort order (asc/desc). :return: Maximum number alerts to get in Maximum number alerts to get in "get_multiple_incidents_extra_data" is 50, not sorted """ global ALERTS_LIMIT_PER_INCIDENTS request_data = { "search_to": limit, "sort": { "field": sort_field or "creation_time", "keyword": sort_order or "asc", }, "full_alert_fields": True, } if search_from is not None: request_data["search_from"] = search_from filters: list[dict] = [] if incident_id_list: incident_id_list = argToList(incident_id_list, transform=str) filters.append({"field": "incident_id_list", "operator": "in", "value": incident_id_list}) if statuses: filters.append({"field": "status", "operator": "in", "value": statuses}) if lte_creation_time_milliseconds: filters.append({"field": "creation_time", "operator": "lte", "value": lte_creation_time_milliseconds}) demisto.debug(f"{excluded_alert_fields=}, {remove_nulls_from_alerts=}, {exclude_artifacts=}") if exclude_artifacts: request_data["fields_to_exclude"] = FIELDS_TO_EXCLUDE if excluded_alert_fields: request_data["alert_fields_to_exclude"] = excluded_alert_fields if remove_nulls_from_alerts: request_data["drop_nulls"] = True if starred and starred_incidents_fetch_window: filters.append({"field": "starred", "operator": "eq", "value": True}) filters.append({"field": "creation_time", "operator": "gte", "value": starred_incidents_fetch_window}) if demisto.command() == "fetch-incidents": if len(filters) > 0: request_data["filters"] = filters incidents = self.handle_fetch_starred_incidents(limit, page_number, request_data) return incidents elif gte_creation_time_milliseconds: filters.append({"field": "creation_time", "operator": "gte", "value": gte_creation_time_milliseconds}) if len(filters) > 0: request_data["filters"] = filters demisto.debug(f"before fetch: {request_data=}") res = self._http_request( method="POST", url_suffix="/incidents/get_multiple_incidents_extra_data/", json_data={"request_data": request_data}, headers=self.headers, timeout=self.timeout, ) reply = res.get("reply", {}) set_sorted_paths_and_names(reply) if ALERTS_LIMIT_PER_INCIDENTS < 0: ALERTS_LIMIT_PER_INCIDENTS = arg_to_number(reply.get("alerts_limit_per_incident")) or 50 demisto.debug(f"Setting alerts limit per incident to {ALERTS_LIMIT_PER_INCIDENTS}") # pop the incidents and then log the reply data so as not to overload the logs incidents = reply.pop("incidents", []) if isinstance(reply, dict) else reply # type: ignore demisto.debug(f"reply data: {reply}") demisto.debug(f'Incidents fetched: {[i.get("incident", i).get("incident_id") for i in incidents]}') return incidents def update_alerts_in_xdr_request(self, alerts_ids, severity, status, comment) -> List[Any]: request_data = { "request_data": { "alert_id_list": alerts_ids, } } update_data = assign_params(severity=severity, status=status, comment=comment) request_data["request_data"]["update_data"] = update_data response = self._http_request( method="POST", url_suffix="/alerts/update_alerts", json_data=request_data, headers=self.headers, timeout=self.timeout, ) if "reply" not in response or "alerts_ids" not in response["reply"]: raise DemistoException(f"Parse Error. Response not in format, can't find reply key. The response {response}.") return response["reply"]["alerts_ids"] def get_biocs(self, request_data: dict): reply = self._http_request( method="POST", url_suffix="/bioc/get", json_data=request_data, ) return reply def insert_or_update_biocs(self, request_data): reply = self._http_request( method="POST", url_suffix="/bioc/insert", json_data=request_data, ) return reply def delete_biocs(self, request_data: dict): reply = self._http_request( method="POST", url_suffix="/bioc/delete", json_data=request_data, ) return reply def get_correlation_rules(self, request_data: dict): reply = self._http_request( method="POST", url_suffix="/correlations/get", json_data=request_data, ) return reply def create_or_update_correlation_rules(self, request_data: dict): reply = self._http_request( method="POST", url_suffix="/correlations/insert", json_data=request_data, ) return reply def delete_correlation_rules(self, request_data: dict): reply = self._http_request( method="POST", url_suffix="/correlations/delete", json_data=request_data, ) return reply def get_asset(self, asset_id: str): try: res = self._http_request( method="GET", url_suffix=f"/assets/{asset_id}", ) return res.get("reply", {}).get("data", []) except DemistoException as e: raise DemistoException(f"Error for asset with ID {asset_id}: {e.message}") def list_assets(self, request_data: dict): res = self._http_request( method="POST", url_suffix="/assets", json_data=request_data, ) return res.get("reply", {}).get("data", []) def get_asset_schema(self): res = self._http_request( method="GET", url_suffix="/assets/schema", ) return res.get("reply", {}).get("data", []) def get_asset_schema_field_options(self, field_name: str): res = self._http_request( method="GET", url_suffix=f"/assets/enum/{field_name}", ) return res.get("reply", {}).get("data", []) def create_asset_group(self, request_data: dict): res = self._http_request( method="POST", url_suffix="/asset-groups/create", json_data=request_data, ) return res.get("reply", {}) def delete_asset_group(self, group_id: str): self._http_request( method="POST", url_suffix=f"/asset-groups/delete/{group_id}", ) def list_asset_groups(self, request_data: dict): res = self._http_request( method="POST", url_suffix="/asset-groups", json_data=request_data, ) return res.get("reply", {}).get("data", []) def update_asset_group(self, group_id: str, request_data: dict): self._http_request( method="POST", url_suffix=f"/asset-groups/update/{group_id}", json_data=request_data, ) def get_vulnerability_details(self, vulnerability_id: str): """ Gets vulnerability details by ID. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Vulnerabilities """ res = self._http_request( method="GET", url_suffix="../uvem/v1/vulnerabilities", # we want to remove the v1 from the endpoint so we use .. params={"vulnerabilityId": vulnerability_id}, ) return res def run_healthcheck(self): """ Runs a system health check. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/System-Health-Check """ res = self._http_request( method="GET", url_suffix="/healthcheck", ) return res def get_triage_presets(self): """ Gets triage presets. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Get-triage-presets """ res = self._http_request( method="POST", url_suffix="/get_triage_presets", json_data={"request_data": {}}, # required to be empty ) return res.get("reply", {}).get("triage_presets", []) def triage_endpoint(self, request_data: dict): """ Initiates forensics triage on endpoints. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Initiate-Forensics-Triage """ res = self._http_request( method="POST", url_suffix="/triage_endpoint", json_data=request_data, ) return res.get("reply", {}) def create_automation_script(self, files: dict): """ Creates or updates an automation script by uploading a file. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Insert-or-update-a-script Args: files (dict): A dictionary containing the file to upload, e.g. {'file': (filename, file_content)}. Returns: dict: The API response. """ res = self._http_request( method="POST", url_suffix="/scripts/insert", files=files, ) return res def get_automation_script(self, request_data: dict) -> bytes: """ Gets an automation script. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Get-a-script Args: request_data (dict): The request data containing the filter to identify the script. Returns: bytes: The script file content. """ return self._http_request(method="POST", url_suffix="/scripts/get", json_data=request_data, resp_type="content") def delete_automation_script(self, request_data: dict): """ Deletes an automation script. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Delete-API-keys Args: request_data (dict): The request data containing the filter to identify the script to delete. """ self._http_request( method="POST", url_suffix="/scripts/delete", json_data=request_data, ) def create_automation_playbook(self, files: dict): """ Creates or updates an automation playbook by uploading a file. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Insert-or-update-playbooks Args: files (dict): A dictionary containing the file to upload, e.g. {'file': (filename, file_content)}. Returns: dict: The API response. """ return self._http_request( method="POST", url_suffix="/playbooks/insert", files=files, ) def get_automation_playbook(self, request_data: dict) -> bytes: """ Gets an automation playbook. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Get-a-playbook Args: request_data (dict): The request data containing the filter to identify the playbook. Returns: bytes: The playbook file content. """ return self._http_request( method="POST", url_suffix="/playbooks/get", json_data=request_data, resp_type="content", ) def delete_automation_playbook(self, request_data: dict): """ Deletes an automation playbook. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Delete-a-playbook Args: request_data (dict): The request data containing the filter to identify the playbook to delete. """ self._http_request( method="POST", url_suffix="/playbooks/delete", json_data=request_data, ) def search_cases(self, request_data: dict): res = self._http_request( method="POST", url_suffix="/case/search", json_data=request_data, ) return res.get("reply", {}).get("DATA", []) def update_case(self, case_id: str, request_data: dict): return self._http_request( method="POST", url_suffix=f"/case/update/{case_id}", json_data=request_data, resp_type="response" ) def get_case_artifacts(self, case_id: str): res = self._http_request( method="GET", url_suffix=f"/case/artifacts/{case_id}", ) return res def list_issues(self, request_data: dict) -> list: res = self._http_request( method="POST", url_suffix="/issue/search", json_data=request_data, ) return res.get("reply", {}).get("DATA", []) def create_issue(self, request_data: dict) -> dict: res = self._http_request( method="POST", url_suffix="/issue", json_data=request_data, ) return res.get("reply", {}) def update_issue(self, issue_id: str, request_data: dict) -> None: self._http_request(method="POST", url_suffix=f"/issue/{issue_id}", json_data=request_data, resp_type="response") def extract_paths_and_names(paths: list) -> tuple: """ Takes the output of map_file_path_to_file_name and returns two lists. :param file_mapping: Dictionary mapping file names to file paths :return: Tuple containing (list of file paths, list of file names) """ from pathlib import PureWindowsPath, PurePosixPath if not paths: return [], [] file_mapping = {p: (PureWindowsPath(p).name if "\\" in p else PurePosixPath(p).name) for p in paths} file_paths = list(file_mapping.keys()) file_names = list(file_mapping.values()) return file_paths, file_names def set_sorted_paths_and_names(reply: dict): """ Processes file paths in alerts data and sorts them with corresponding file names. Handles two different response formats: - Single incident response from incidents/get_incident_extra_data endpoint - Multiple incidents response from incidents/get_multiple_incidents_extra_data endpoint For each alert found, extracts file paths and updates the alert data with sorted file paths and corresponding file names. :param reply: Response dictionary containing either single incident or multiple incidents data :return: None (modifies the reply dictionary in-place) """ alerts_data = reply.get("alerts", {}).get("data", []) if alerts_data: update_alerts_file_data(alerts_data) else: incidents = reply.get("incidents", []) for incident in incidents: alerts_data = incident.get("alerts", {}).get("data", []) update_alerts_file_data(alerts_data) def update_alerts_file_data(alerts_data): """ Updates alert data with sorted file paths and corresponding file names. Iterates through alert data and processes file paths for each alert, replacing the original file paths with sorted paths and adding corresponding file names. :param alerts_data: List of alert dictionaries containing file path data :return: None (modifies the alerts_data list in-place) """ for alert in alerts_data: alert_paths = alert.get("action_file_path", []) paths, names = extract_paths_and_names(alert_paths) alert["action_file_path"] = paths alert["action_file_name"] = names def get_headers(params: dict) -> dict: api_key = params.get("apikey_creds", {}).get("password", "") or params.get("apikey", "") api_key_id = params.get("apikey_id_creds", {}).get("password", "") or params.get("apikey_id") nonce: str = "".join([secrets.choice(string.ascii_letters + string.digits) for _ in range(64)]) timestamp: str = str(int(datetime.now(timezone.utc).timestamp()) * 1000) auth_key = f"{api_key}{nonce}{timestamp}" auth_key = auth_key.encode("utf-8") api_key_hash: str = hashlib.sha256(auth_key).hexdigest() if argToBoolean(params.get("prevent_only", False)): api_key_hash = api_key headers: dict = { "x-xdr-timestamp": timestamp, "x-xdr-nonce": nonce, "x-xdr-auth-id": str(api_key_id), "Authorization": api_key_hash, } return headers def get_tenant_info_command(client: Client): tenant_info = client.get_tenant_info() readable_output = tableToMarkdown( "Tenant Information", tenant_info, headerTransform=pascalToSpace, removeNull=True, is_auto_json_transform=True ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.TenantInformation", outputs=tenant_info, raw_response=tenant_info, ) def update_incident_command(client, args): incident_id = args.get("incident_id") assigned_user_mail = args.get("assigned_user_mail") status = args.get("status") demisto.debug(f"this_is_the_status {status}") severity = args.get("manual_severity") unassign_user = args.get("unassign_user") == "true" resolve_comment = args.get("resolve_comment") add_comment = args.get("add_comment") resolve_alerts = argToBoolean(args.get("resolve_alerts", False)) client.update_incident( incident_id=incident_id, assigned_user_mail=assigned_user_mail, unassign_user=unassign_user, status=status, severity=severity, resolve_comment=resolve_comment, add_comment=add_comment, ) is_closed = resolve_comment or (status and argToList(status, "_")[0] == "RESOLVED") if resolve_alerts and is_closed: args["status"] = args["status"].lower() update_related_alerts(client, args) return f"Incident {incident_id} has been updated", None, None def check_if_incident_was_modified_in_xdr(incident_id, last_mirrored_in_time_timestamp, last_modified_incidents_dict): if incident_id in last_modified_incidents_dict: # search the incident in the dict of modified incidents incident_modification_time_in_xdr = int(str(last_modified_incidents_dict[incident_id])) demisto.debug( f"XDR incident {incident_id}\n" f"modified time: {incident_modification_time_in_xdr}\n" f"last mirrored in time: {last_mirrored_in_time_timestamp}" ) if incident_modification_time_in_xdr > last_mirrored_in_time_timestamp: # need to update this incident demisto.info(f"Incident '{incident_id}' was modified. performing extra-data request.") return True # the incident was not modified return False def get_last_mirrored_in_time(args): demisto_incidents = demisto.get_incidents() # type: ignore if demisto_incidents: # handling 5.5 version demisto_incident = demisto_incidents[0] last_mirrored_in_time = demisto_incident.get("CustomFields", {}).get("lastmirroredintime") if not last_mirrored_in_time: # this is an old incident, update anyway return 0 last_mirrored_in_timestamp = arg_to_timestamp(last_mirrored_in_time, "last_mirrored_in_time") else: # handling 6.0 version last_mirrored_in_time = arg_to_timestamp(args.get("last_update"), "last_update") last_mirrored_in_timestamp = last_mirrored_in_time - (120 * 1000) return last_mirrored_in_timestamp def sort_incident_data(raw_incident): """ Sorts and processes the raw incident data into a cleaned incident dict. Parameters: - raw_incident (dict): The raw incident data as provided by the API. Returns: - dict: A dictionary containing the processed incident data with: - organized alerts. - file artifact - network artifacts. """ incident = raw_incident.get("incident", {}) raw_alerts = raw_incident.get("alerts", {}).get("data", []) file_artifacts = raw_incident.get("file_artifacts", {}).get("data", []) network_artifacts = raw_incident.get("network_artifacts", {}).get("data", []) context_alerts = clear_trailing_whitespace(raw_alerts) if context_alerts: for alert in context_alerts: alert["host_ip_list"] = alert.get("host_ip").split(",") if alert.get("host_ip") else [] incident.update({"alerts": context_alerts, "file_artifacts": file_artifacts, "network_artifacts": network_artifacts}) return incident def get_incident_extra_data_command(client, args): global ALERTS_LIMIT_PER_INCIDENTS incident_id = args.get("incident_id") alerts_limit = int(args.get("alerts_limit", 1000)) exclude_artifacts = argToBoolean(args.get("excluding_artifacts", "False")) alert_fields_to_exclude = args.get("alert_fields_to_exclude", []) drop_nulls = args.get("drop_nulls", False) demisto.debug(f"{exclude_artifacts=} , {alert_fields_to_exclude=}, {drop_nulls=}") return_only_updated_incident = argToBoolean(args.get("return_only_updated_incident", "False")) if return_only_updated_incident: last_mirrored_in_time = get_last_mirrored_in_time(args) last_modified_incidents_dict = get_integration_context().get("modified_incidents", {}) if check_if_incident_was_modified_in_xdr(incident_id, last_mirrored_in_time, last_modified_incidents_dict): pass # the incident was modified. continue to perform extra-data request else: # the incident was not modified return "The incident was not modified in XDR since the last mirror in.", {}, {} raw_incident = client.get_multiple_incidents_extra_data( incident_id_list=[incident_id], exclude_artifacts=exclude_artifacts, excluded_alert_fields=alert_fields_to_exclude, remove_nulls_from_alerts=drop_nulls, ) if not raw_incident: raise DemistoException(f"Incident {incident_id} is not found") if isinstance(raw_incident, list): raw_incident = raw_incident[0] if raw_incident.get("incident", {}).get("alert_count") > ALERTS_LIMIT_PER_INCIDENTS: demisto.debug(f'for incident:{incident_id} using the old call since "\ "alert_count:{raw_incident.get("incident", {}).get("alert_count")} >" \ "limit:{ALERTS_LIMIT_PER_INCIDENTS}') raw_incident = client.get_incident_extra_data( incident_id, alerts_limit, exclude_artifacts=exclude_artifacts, excluded_alert_fields=alert_fields_to_exclude, remove_nulls_from_alerts=drop_nulls, ) readable_output = [tableToMarkdown(f"Incident {incident_id}", raw_incident.get("incident"), removeNull=True)] incident = sort_incident_data(raw_incident) if incident_alerts := incident.get("alerts"): readable_output.append( tableToMarkdown( "Alerts", incident_alerts, headers=[key for key in incident_alerts[0] if key != "host_ip"], removeNull=True ) ) readable_output.append(tableToMarkdown("Network Artifacts", incident.get("network_artifacts"), removeNull=True)) readable_output.append(tableToMarkdown("File Artifacts", incident.get("file_artifacts"), removeNull=True)) account_context_output = assign_params(Username=incident.get("users", "")) endpoint_context_output = [] for alert in incident.get("alerts") or []: alert_context = {} if hostname := alert.get("host_name"): alert_context["Hostname"] = hostname if endpoint_id := alert.get("endpoint_id"): alert_context["ID"] = endpoint_id if alert_context: endpoint_context_output.append(alert_context) context_output = {f"{INTEGRATION_CONTEXT_BRAND}.Incident(val.incident_id==obj.incident_id)": incident} if account_context_output: context_output["Account(val.Username==obj.Username)"] = account_context_output if endpoint_context_output: context_output["Endpoint(val.Hostname==obj.Hostname)"] = endpoint_context_output file_context, process_context, domain_context, ip_context = get_indicators_context(incident) if file_context: context_output[Common.File.CONTEXT_PATH] = file_context if domain_context: context_output[Common.Domain.CONTEXT_PATH] = domain_context if ip_context: context_output[Common.IP.CONTEXT_PATH] = ip_context if process_context: context_output["Process(val.Name && val.Name == obj.Name)"] = process_context return ("\n".join(readable_output), context_output, raw_incident) def create_parsed_alert( product, vendor, local_ip, local_port, remote_ip, remote_port, event_timestamp, severity, alert_name, alert_description ): alert = { "product": product, "vendor": vendor, "local_ip": local_ip, "local_port": local_port, "remote_ip": remote_ip, "remote_port": remote_port, "event_timestamp": event_timestamp, "severity": severity, "alert_name": alert_name, "alert_description": alert_description, } return alert def insert_parsed_alert_command(client, args): product = args.get("product") vendor = args.get("vendor") local_ip = args.get("local_ip") local_port = arg_to_int(arg=args.get("local_port"), arg_name="local_port") remote_ip = args.get("remote_ip") remote_port = arg_to_int(arg=args.get("remote_port"), arg_name="remote_port") severity = args.get("severity") alert_name = args.get("alert_name") alert_description = args.get("alert_description", "") event_timestamp = int(round(time.time() * 1000)) if args.get("event_timestamp") is None else int(args.get("event_timestamp")) alert = create_parsed_alert( product=product, vendor=vendor, local_ip=local_ip, local_port=local_port, remote_ip=remote_ip, remote_port=remote_port, event_timestamp=event_timestamp, severity=severity, alert_name=alert_name, alert_description=alert_description, ) client.insert_alerts([alert]) return ("Alert inserted successfully", None, None) def insert_cef_alerts_command(client, args): # parsing alerts list. the reason we don't use argToList is because cef_alerts could contain comma (,) so # we shouldn't split them by comma alerts = args.get("cef_alerts") if isinstance(alerts, list): pass elif isinstance(alerts, str): alerts = json.loads(alerts) if alerts[0] == "[" and alerts[-1] == "]" else [alerts] else: raise ValueError('Invalid argument "cef_alerts". It should be either list of strings (cef alerts), or single string') client.insert_cef_alerts(alerts) return ("Alerts inserted successfully", None, None) def sort_all_list_incident_fields(incident_data): """Sorting all lists fields in an incident - without this, elements may shift which results in false identification of changed fields""" if incident_data.get("hosts", []): incident_data["hosts"] = sorted(incident_data.get("hosts", [])) incident_data["hosts"] = [host.upper() for host in incident_data.get("hosts", [])] if incident_data.get("users", []): incident_data["users"] = sorted(incident_data.get("users", [])) incident_data["users"] = [user.upper() for user in incident_data.get("users", [])] if incident_data.get("incident_sources", []): incident_data["incident_sources"] = sorted(incident_data.get("incident_sources", [])) format_sublists = not argToBoolean(demisto.params().get("dont_format_sublists", False)) if incident_data.get("alerts", []): incident_data["alerts"] = sort_by_key(incident_data.get("alerts", []), main_key="alert_id", fallback_key="name") if format_sublists: reformat_sublist_fields(incident_data["alerts"]) if incident_data.get("file_artifacts", []): incident_data["file_artifacts"] = sort_by_key( incident_data.get("file_artifacts", []), main_key="file_name", fallback_key="file_sha256" ) if format_sublists: reformat_sublist_fields(incident_data["file_artifacts"]) if incident_data.get("network_artifacts", []): incident_data["network_artifacts"] = sort_by_key( incident_data.get("network_artifacts", []), main_key="network_domain", fallback_key="network_remote_ip" ) if format_sublists: reformat_sublist_fields(incident_data["network_artifacts"]) def sync_incoming_incident_owners(incident_data): if incident_data.get("assigned_user_mail") and demisto.params().get("sync_owners"): user_info = demisto.findUser(email=incident_data.get("assigned_user_mail")) if user_info: demisto.debug( f"Syncing incident owners: XDR incident {incident_data.get('incident_id')}, owner {user_info.get('username')}" ) incident_data["owner"] = user_info.get("username") else: demisto.debug(f"The user assigned to XDR incident {incident_data.get('incident_id')} is not registered on XSOAR") def handle_incoming_user_unassignment(incident_data): incident_data["assigned_user_mail"] = "" incident_data["assigned_user_pretty_name"] = "" if demisto.params().get("sync_owners"): demisto.debug(f'Unassigning owner from XDR incident {incident_data.get("incident_id")}') incident_data["owner"] = "" def resolve_xsoar_close_reason(xdr_close_reason: str): """ Resolving XSOAR close reason from possible custom XDR->XSOAR close-reason mapping or default mapping. :param xdr_close_reason: XDR raw status/close reason e.g. 'resolved_false_positive'. :return: XSOAR close reason. """ possible_xsoar_close_reasons = get_xsoar_close_reasons() # Check if incoming XDR close-reason has a non-default mapping to XSOAR close-reason. if demisto.params().get("custom_xdr_to_xsoar_close_reason_mapping"): custom_xdr_to_xsoar_close_reason_mapping = comma_separated_mapping_to_dict( demisto.params().get("custom_xdr_to_xsoar_close_reason_mapping") ) # XDR raw status/close-reason is prefixed with 'resolved_' and is given in snake_case format, # e.g. 'resolved_false_positive', whilst custom XDR->XSOAR close-reason mapping # is using title case format e.g. 'False Positive', therefore we need to adapt it accordingly. title_cased_xdr_close_reason = xdr_close_reason.replace("resolved_", "").replace("_", " ").title() xsoar_close_reason = custom_xdr_to_xsoar_close_reason_mapping.get(title_cased_xdr_close_reason) if xsoar_close_reason in possible_xsoar_close_reasons: demisto.debug(f"XDR->XSOAR custom close-reason exists, using {xdr_close_reason}={xsoar_close_reason}") return xsoar_close_reason # Otherwise, we use default mapping. xsoar_close_reason = XDR_RESOLVED_STATUS_TO_XSOAR.get(xdr_close_reason) demisto.debug( f"XDR->XSOAR custom close-reason does not exists, using default mapping {xdr_close_reason}={xsoar_close_reason}" ) return xsoar_close_reason def close_incident_in_xsoar(incident_data): xsoar_close_reason = resolve_xsoar_close_reason(incident_data.get("status")) closing_entry: dict = { "Type": EntryType.NOTE, "Contents": { "dbotIncidentClose": True, "closeReason": xsoar_close_reason, "closeNotes": incident_data.get("resolve_comment", ""), }, "ContentsFormat": EntryFormat.JSON, } incident_data["closeReason"] = closing_entry["Contents"]["closeReason"] incident_data["closeNotes"] = closing_entry["Contents"]["closeNotes"] demisto.debug(f"close_incident_in_xsoar {incident_data['closeReason']=} {incident_data['closeNotes']=}") if incident_data.get("status") == "resolved_known_issue": close_notes = f'Known Issue.\n{incident_data.get("closeNotes", "")}' closing_entry["Contents"]["closeNotes"] = close_notes incident_data["closeNotes"] = close_notes demisto.debug(f"close_incident_in_xsoar {close_notes=}") demisto.debug(f"The closing entry, {closing_entry=}") return closing_entry def reopen_incident_in_xsoar(): opening_entry = {"Type": EntryType.NOTE, "Contents": {"dbotIncidentReopen": True}, "ContentsFormat": EntryFormat.JSON} demisto.debug(f"The opening entry, {opening_entry=}") return opening_entry def handle_incoming_incident(incident_data) -> dict: incident_id = incident_data.get("incident_id") incoming_incident_status = incident_data.get("status") demisto.debug(f"handle_incoming_incident {incoming_incident_status=}, {incident_id=}, {incident_data=}") if incoming_incident_status in XDR_RESOLVED_STATUS_TO_XSOAR: demisto.debug(f"handle_incoming_incident Incident is closed: {incident_id}") return close_incident_in_xsoar(incident_data) elif incoming_incident_status in XDR_OPEN_STATUS_TO_XSOAR: demisto.debug(f"handle_incoming_incident Incident is opened (or reopened): {incident_id}") return reopen_incident_in_xsoar() return {} def get_mapping_fields_command(): xdr_incident_type_scheme = SchemeTypeMapping(type_name=XDR_INCIDENT_TYPE_NAME) for field in XDR_INCIDENT_FIELDS: xdr_incident_type_scheme.add_field(name=field, description=XDR_INCIDENT_FIELDS[field].get("description")) mapping_response = GetMappingFieldsResponse() mapping_response.add_scheme_type(xdr_incident_type_scheme) return mapping_response def get_modified_remote_data_command(client, args, mirroring_last_update: str = "", xdr_delay: int = 1): remote_args = GetModifiedRemoteDataArgs(args) last_update: str if mirroring_last_update: last_update = mirroring_last_update demisto.debug(f"using {mirroring_last_update=} for last_update") else: last_update = remote_args.last_update demisto.debug(f"using {remote_args.last_update=} for last_update") if not last_update: default_last_update = datetime_to_string(datetime.utcnow() - timedelta(minutes=xdr_delay + 1)) demisto.debug(f"Mirror last update is: {last_update=} will set it to {default_last_update=}") last_update = default_last_update last_update_utc = dateparser.parse( last_update, settings={"TIMEZONE": "UTC", "RETURN_AS_TIMEZONE_AWARE": False} ) # convert to utc format if not last_update_utc: raise DemistoException(f"Failed to parse {last_update=} got {last_update_utc=}") gte_modification_time_milliseconds = last_update_utc lte_modification_time_milliseconds = datetime.utcnow() - timedelta(minutes=xdr_delay) demisto.debug( f"Performing get-modified-remote-data command {last_update=} | {gte_modification_time_milliseconds=} |" f"{lte_modification_time_milliseconds=}" ) raw_incidents = client.get_incidents( gte_modification_time_milliseconds=gte_modification_time_milliseconds, lte_modification_time_milliseconds=lte_modification_time_milliseconds, limit=100, ) last_run_mirroring = lte_modification_time_milliseconds + timedelta(milliseconds=1) last_run_mirroring_str = last_run_mirroring.strftime("%Y-%m-%d %H:%M:%S.%f")[:-3] id_to_modification_time = {raw.get("incident_id"): raw.get("modification_time") for raw in raw_incidents} demisto.debug(f"{last_run_mirroring_str=}, modified incidents {id_to_modification_time=}") return GetModifiedRemoteDataResponse(list(id_to_modification_time.keys())), last_run_mirroring_str def get_remote_data_command(client, args, excluded_alert_fields=[], remove_nulls_from_alerts=False): demisto.debug(f"{excluded_alert_fields=}, {remove_nulls_from_alerts=}") remote_args = GetRemoteDataArgs(args) demisto.debug(f"Performing get-remote-data command with incident id: {remote_args.remote_incident_id}") incident_data = {} try: # when Demisto version is 6.1.0 and above, this command will only be automatically executed on incidents # returned from get_modified_remote_data_command so we want to perform extra-data request on those incidents. return_only_updated_incident = not is_demisto_version_ge("6.1.0") # True if version is below 6.1 else False requested_data = { "incident_id": remote_args.remote_incident_id, "alerts_limit": 1000, "return_only_updated_incident": return_only_updated_incident, "last_update": remote_args.last_update, } if excluded_alert_fields: requested_data["alert_fields_to_exclude"] = excluded_alert_fields if remove_nulls_from_alerts: requested_data["drop_nulls"] = True incident_data = get_incident_extra_data_command(client, requested_data) if "The incident was not modified" not in incident_data[0]: demisto.debug(f"Updating XDR incident {remote_args.remote_incident_id}") incident_data = incident_data[2].get("incident") incident_data["id"] = incident_data.get("incident_id") sort_all_list_incident_fields(incident_data) # deleting creation time as it keeps updating in the system del incident_data["creation_time"] # handle unasignment if incident_data.get("assigned_user_mail") is None: handle_incoming_user_unassignment(incident_data) else: # handle owner sync sync_incoming_incident_owners(incident_data) # handle closed issue in XDR and handle outgoing error entry entries = [] if argToBoolean(client._params.get("close_xsoar_incident", True)): entries = [handle_incoming_incident(incident_data)] reformatted_entries = [] for entry in entries: if entry: reformatted_entries.append(entry) incident_data["in_mirror_error"] = "" return GetRemoteDataResponse(mirrored_object=incident_data, entries=reformatted_entries) else: # no need to update this incident incident_data = {"id": remote_args.remote_incident_id, "in_mirror_error": ""} return GetRemoteDataResponse(mirrored_object=incident_data, entries=[]) except Exception as e: demisto.debug(f"Error in XDR incoming mirror for incident {remote_args.remote_incident_id} \nError message: {e!s}") if "Rate limit exceeded" in str(e): return_error("API rate limit") if incident_data: incident_data["in_mirror_error"] = str(e) sort_all_list_incident_fields(incident_data) # deleting creation time as it keeps updating in the system del incident_data["creation_time"] else: incident_data = {"id": remote_args.remote_incident_id, "in_mirror_error": str(e)} return GetRemoteDataResponse(mirrored_object=incident_data, entries=[]) def update_remote_system_command(client, args): parsed_args = UpdateRemoteSystemArgs(args) demisto.debug( f"update_remote_system_command command args are:" f"id: {parsed_args.remote_incident_id}, " f"data: {parsed_args.data}, " f"entries: {parsed_args.entries}, " f"incident_changed: {parsed_args.incident_changed}, " f"remote_incident_id: {parsed_args.remote_incident_id}, " f"inc_status: {parsed_args.inc_status}, " f"delta: {parsed_args.delta}" ) try: if parsed_args.incident_changed: demisto.debug( f"For incident ID: {parsed_args.remote_incident_id} got the following" f" delta keys {list(parsed_args.delta.keys())!s} to update." ) xsoar_to_xdr_delta = get_update_args(parsed_args) demisto.debug(f"update_remote_system_command: After returning from get_update_args, {xsoar_to_xdr_delta=}") xsoar_to_xdr_delta["incident_id"] = parsed_args.remote_incident_id should_close_xdr_incident = argToBoolean(client._params.get("close_xdr_incident", True)) status = "" # If the client does not want to close the incident in XDR, temporarily remove the status from the arguments # to update the incident, and add it back later to close the alerts. if not should_close_xdr_incident and (xsoar_to_xdr_delta.get("status") in XSOAR_RESOLVED_STATUS_TO_XDR.values()): status = xsoar_to_xdr_delta.pop("status") resolve_comment = xsoar_to_xdr_delta.pop("resolve_comment", None) demisto.debug( f"Popped status {status} and {resolve_comment=} from update_args," f" incident status won't be updated in XDR." ) demisto.debug(f"update_remote_system_command: Update incident with the following delta {xsoar_to_xdr_delta}") update_incident_command(client, xsoar_to_xdr_delta) # updating xdr with the delta should_close_alerts_in_xdr = argToBoolean(client._params.get("close_alerts_in_xdr", False)) if should_close_alerts_in_xdr and xsoar_to_xdr_delta.get("status") in XDR_RESOLVED_STATUS_TO_XSOAR: if status: xsoar_to_xdr_delta["status"] = status demisto.debug(f"Restored {status=} in order to update the alerts status.") update_related_alerts(client, xsoar_to_xdr_delta) demisto.debug("update_remote_system_command: closed xdr alerts") else: demisto.debug( f"Skipping updating remote incident fields [{parsed_args.remote_incident_id}] as it is not new nor changed" ) return parsed_args.remote_incident_id except Exception as e: demisto.debug(f"Error in outgoing mirror for incident {parsed_args.remote_incident_id} \nError message: {e!s}") return parsed_args.remote_incident_id def update_related_alerts(client: Client, args: dict): new_status = args.get("status") incident_id = args.get("incident_id") comment = f"Resolved by XSOAR, due to incident {incident_id} that has been resolved." demisto.debug(f"{new_status=}, {comment=}") if not new_status: raise DemistoException(f"Failed to update alerts related to incident {incident_id},no status found") incident_extra_data = client.get_incident_extra_data(incident_id=incident_id) if "alerts" in incident_extra_data and "data" in incident_extra_data["alerts"]: alerts_array = incident_extra_data["alerts"]["data"] related_alerts_ids_array = [str(alert["alert_id"]) for alert in alerts_array if "alert_id" in alert] demisto.debug(f"{related_alerts_ids_array=}") args_for_command = {"alert_ids": related_alerts_ids_array, "status": new_status, "comment": comment} return_results(update_alerts_in_xdr_command(client, args_for_command)) def fetch_incidents( client: Client, first_fetch_time, integration_instance, exclude_artifacts: bool, last_run: dict, max_fetch: int = 10, statuses: list = [], starred: Optional[bool] = None, starred_incidents_fetch_window: str = None, excluded_alert_fields: list = [], remove_nulls_from_alerts: bool = True, ): global ALERTS_LIMIT_PER_INCIDENTS # Get the last fetch time, if exists last_fetch = last_run.get("time") incidents_from_previous_run = last_run.get("incidents_from_previous_run", []) next_dedup_incidents = dedup_incidents = last_run.get("dedup_incidents") or [] demisto.debug(f"{incidents_from_previous_run=}") # Handle first time fetch, fetch incidents retroactively if last_fetch is None: last_fetch, _ = parse_date_range(first_fetch_time, to_timestamp=True) demisto.debug(f"last_fetch after parsing date range {last_fetch}") if starred: starred_incidents_fetch_window, _ = parse_date_range(starred_incidents_fetch_window, to_timestamp=True) demisto.debug(f"starred_incidents_fetch_window after parsing date range {starred_incidents_fetch_window}") if incidents_from_previous_run: demisto.debug("Using incidents from last run") raw_incidents = incidents_from_previous_run ALERTS_LIMIT_PER_INCIDENTS = last_run.get("alerts_limit_per_incident", -1) demisto.debug(f"{ALERTS_LIMIT_PER_INCIDENTS=}") else: demisto.debug("Fetching incidents") raw_incidents = client.get_multiple_incidents_extra_data( gte_creation_time_milliseconds=last_fetch, # adding len of deduped events so that we don't loop on the same incidents infinitely. # There might be a case where deduped incident doesn't come back and we are returning more than the limit. statuses=statuses, limit=max_fetch + len(dedup_incidents), starred=starred, starred_incidents_fetch_window=starred_incidents_fetch_window, exclude_artifacts=exclude_artifacts, excluded_alert_fields=excluded_alert_fields, remove_nulls_from_alerts=remove_nulls_from_alerts, ) # remove duplicate incidents raw_incidents = [inc for inc in raw_incidents if inc.get("incident", inc).get("incident_id") not in dedup_incidents] # save the last 100 modified incidents to the integration context - for mirroring purposes client.save_modified_incidents_to_integration_context() # maintain a list of non created incidents in a case of a rate limit exception non_created_incidents: list = raw_incidents.copy() try: incidents = [] for raw_incident in raw_incidents: incident_data: dict[str, Any] = sort_incident_data(raw_incident) if raw_incident.get("incident") else raw_incident incident_id = incident_data.get("incident_id") incident_name = incident_data.get("incident_name") alert_count = arg_to_number(incident_data.get("alert_count")) or 0 if alert_count > ALERTS_LIMIT_PER_INCIDENTS: demisto.debug(f'for incident:{incident_id} using the old call since alert_count:{alert_count} >" \ "limit:{ALERTS_LIMIT_PER_INCIDENTS}') raw_incident_ = client.get_incident_extra_data( incident_id=incident_id, exclude_artifacts=exclude_artifacts, excluded_alert_fields=excluded_alert_fields, remove_nulls_from_alerts=remove_nulls_from_alerts, ) incident_data = sort_incident_data(raw_incident_) sort_all_list_incident_fields(incident_data) incident_data |= { "mirror_direction": MIRROR_DIRECTION.get(demisto.params().get("mirror_direction", "None")), "mirror_instance": integration_instance, "last_mirrored_in": int(datetime.now().timestamp() * 1000), } description = incident_data.get("description") occurred = timestamp_to_datestring(incident_data["creation_time"], TIME_FORMAT + "Z") incident: dict[str, Any] = { "name": f"XDR Incident {incident_id} - {incident_name or description}", "occurred": occurred, "rawJSON": json.dumps(incident_data), "details": description, } if demisto.params().get("sync_owners") and incident_data.get("assigned_user_mail"): incident["owner"] = demisto.findUser(email=incident_data["assigned_user_mail"]).get("username") # Update last run and add incident if the incident is newer than last fetch creation_time = incident_data.get("creation_time", 0) demisto.debug(f"creation time for {incident_id=} {creation_time=}") if creation_time > last_fetch: demisto.debug(f"updating last_fetch, {incident_id=}") last_fetch = incident_data["creation_time"] next_dedup_incidents = [incident_id] elif creation_time == last_fetch: demisto.debug(f"got incident at same time for dedup, {incident_id=}") next_dedup_incidents.append(incident_id) else: demisto.debug(f"{incident_data['creation_time']=} < last_fetch; {incident_id=}") incidents.append(incident) non_created_incidents.remove(raw_incident) except Exception as e: if "Rate limit exceeded" in str(e): demisto.info( f"Cortex XDR - rate limit exceeded, number of non created incidents is: " f"{len(non_created_incidents)!r}.\n The incidents will be created in the next fetch" ) else: raise next_run = {"incidents_from_previous_run": non_created_incidents, "time": last_fetch, "dedup_incidents": next_dedup_incidents} if non_created_incidents: next_run["alerts_limit_per_incident"] = ALERTS_LIMIT_PER_INCIDENTS # type: ignore[assignment] demisto.debug(f"{next_run=}") return next_run, incidents def get_endpoints_by_status_command(client: Client, args: Dict) -> CommandResults: status = args.get("status") status = argToList(status) last_seen_gte = arg_to_timestamp(arg=args.get("last_seen_gte"), arg_name="last_seen_gte") last_seen_lte = arg_to_timestamp(arg=args.get("last_seen_lte"), arg_name="last_seen_lte") endpoints_count, raw_res = client.get_endpoints_by_status(status, last_seen_gte=last_seen_gte, last_seen_lte=last_seen_lte) ec = {"status": status, "count": endpoints_count} return CommandResults( readable_output=f"{status} endpoints count: {endpoints_count}", outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.EndpointsStatus", outputs_key_field="status", outputs=ec, raw_response=raw_res, ) def file_details_results(client: Client, args: Dict, add_to_context: bool) -> None: return_entry, file_results = retrieve_file_details_command(client, args, add_to_context) demisto.results(return_entry) if file_results: demisto.results(file_results) def get_contributing_event_command(client: Client, args: Dict) -> CommandResults: if alert_ids := argToList(args.get("alert_ids")): alerts = [] for alert_id in alert_ids: if alert := client.get_contributing_event_by_alert_id(int(alert_id)): page_number = max(int(args.get("page_number", 1)), 1) - 1 # Min & default zero (First page) page_size = max(int(args.get("page_size", 50)), 0) # Min zero & default 50 offset = page_number * page_size limit = max(int(args.get("limit", 0)), 0) or offset + page_size alert_with_events = { "alertID": str(alert_id), "events": alert.get("events", [])[offset:limit], } alerts.append(alert_with_events) readable_output = tableToMarkdown( "Contributing events", alerts, headerTransform=pascalToSpace, removeNull=True, is_auto_json_transform=True ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.ContributingEvent", outputs_key_field="alertID", outputs=alerts, raw_response=alerts, ) else: return CommandResults(readable_output="The alert_ids argument cannot be empty.") def replace_featured_field_command(client: Client, args: Dict) -> CommandResults: field_type = args.get("field_type", "") values = argToList(args.get("values")) len_values = len(values) comments = argToList(args.get("comments"))[:len_values] ad_type = argToList(args.get("ad_type", "group"))[:len_values] if field_type == "ad_groups": fields = [ {"value": field[0], "comment": field[1], "type": field[2]} for field in zip_longest(values, comments, ad_type, fillvalue="") ] else: fields = [{"value": field[0], "comment": field[1]} for field in zip_longest(values, comments, fillvalue="")] client.replace_featured_field(field_type, fields) result = {"fieldType": field_type, "fields": fields} readable_output = tableToMarkdown( f'Replaced featured: {result.get("fieldType")}', result.get("fields"), headerTransform=pascalToSpace ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.FeaturedField", outputs_key_field="fieldType", outputs=result, raw_response=result, ) def update_alerts_in_xdr_command(client: Client, args: Dict) -> CommandResults: """ Deprecated. Use update_issue_command (xdr-issue-update) instead. Update one or more alerts with the provided arguments. """ alerts_list = argToList(args.get("alert_ids")) array_of_all_ids = [] severity = args.get("severity") status = args.get("status") comment = args.get("comment") if not severity and not status and not comment: raise DemistoException( f"Can not find a field to update for alerts {alerts_list}, please fill in severity/status/comment." ) # API is limited to 100 alerts per request, doing the request in batches of 100. for index in range(0, len(alerts_list), 100): alerts_sublist = alerts_list[index : index + 100] demisto.debug(f"{alerts_sublist=}, {severity=}, {status=}, {comment=}") array_of_sublist_ids = client.update_alerts_in_xdr_request(alerts_sublist, severity, status, comment) array_of_all_ids += array_of_sublist_ids if not array_of_all_ids: raise DemistoException("Could not find alerts to update, please make sure you used valid alert IDs.") return CommandResults(readable_output="Alerts with IDs {} have been updated successfully.".format(",".join(array_of_all_ids))) def create_filters_for_bioc_and_correlation_rules(args: dict) -> list: """ Creates a list of filters for BIOC and correlation rules based on the provided arguments. Args: args (dict): The command arguments containing filter criteria. Returns: list: A list of filter dictionaries compatible with the Cortex XDR API. """ filters = [] if name := args.get("name"): filters.append({"field": "name", "operator": "EQ", "value": name}) if severity := args.get("severity"): filters.append({"field": "severity", "operator": "EQ", "value": BIOC_AND_CR_SEVERITY_MAPPING.get(severity, severity)}) if bioc_type := args.get("type"): filters.append({"field": "type", "operator": "EQ", "value": bioc_type}) if is_xql := args.get("is_xql"): filters.append({"field": "is_xql", "operator": "EQ", "value": argToBoolean(is_xql)}) if comment := args.get("comment"): filters.append({"field": "comment", "operator": "EQ", "value": comment}) if status := args.get("status"): filters.append({"field": "status", "operator": "EQ", "value": status}) if indicator := args.get("indicator"): filters.append({"field": "indicator", "operator": "EQ", "value": indicator}) if mitre_technique := argToList(args.get("mitre_technique_id_and_name")): filters.append({"field": "mitre_technique_id_and_name", "operator": "EQ", "value": mitre_technique}) if mitre_tactic := argToList(args.get("mitre_tactic_id_and_name")): filters.append({"field": "mitre_tactic_id_and_name", "operator": "EQ", "value": mitre_tactic}) if xql_query := args.get("xql_query"): filters.append({"field": "xql_query", "operator": "EQ", "value": xql_query}) if is_enabled := args.get("is_enabled"): filters.append({"field": "is_enabled", "operator": "EQ", "value": argToBoolean(is_enabled)}) if description := args.get("description"): filters.append({"field": "description", "operator": "EQ", "value": description}) if alert_name := args.get("alert_name"): filters.append({"field": "alert_name", "operator": "EQ", "value": alert_name}) if alert_category := args.get("alert_category"): filters.append({"field": "alert_category", "operator": "EQ", "value": alert_category}) if alert_description := args.get("alert_description"): filters.append({"field": "alert_description", "operator": "EQ", "value": alert_description}) if alert_fields := argToList(args.get("alert_fields")): filters.append({"field": "alert_fields", "operator": "EQ", "value": alert_fields}) if execution_mode := args.get("execution_mode"): filters.append({"field": "execution_mode", "operator": "EQ", "value": execution_mode}) if search_window := args.get("search_window"): filters.append({"field": "search_window", "operator": "EQ", "value": search_window}) if simple_schedule := args.get("schedule"): filters.append({"field": "schedule", "operator": "EQ", "value": simple_schedule}) if timezone := args.get("timezone"): filters.append({"field": "timezone", "operator": "EQ", "value": timezone}) if crontab := args.get("schedule_linux"): filters.append({"field": "schedule_linux", "operator": "EQ", "value": crontab}) if suppression_enabled := args.get("suppression_enabled"): filters.append({"field": "suppression_enabled", "operator": "EQ", "value": argToBoolean(suppression_enabled)}) if suppression_duration := args.get("suppression_duration"): filters.append({"field": "suppression_duration", "operator": "EQ", "value": suppression_duration}) if suppression_fields := args.get("suppression_fields"): filters.append({"field": "suppression_fields", "operator": "EQ", "value": suppression_fields}) if dataset := args.get("dataset"): filters.append({"field": "dataset", "operator": "EQ", "value": dataset}) if user_defined_severity := args.get("user_defined_severity"): filters.append({"field": "user_defined_severity", "operator": "EQ", "value": user_defined_severity}) if user_defined_category := args.get("user_defined_category"): filters.append({"field": "user_defined_category", "operator": "EQ", "value": user_defined_category}) if mitre_defs := args.get("mitre_defs_json"): try: mitre_defs_json = json.loads(mitre_defs) except ValueError: raise DemistoException("Unable to parse 'mitre_defs'. Please use the JSON format.") filters.append({"field": "mitre_defs", "operator": "EQ", "value": mitre_defs_json}) if investigation_query_link := args.get("investigation_query_link"): filters.append({"field": "investigation_query_link", "operator": "EQ", "value": investigation_query_link}) if drilldown_query_timeframe := args.get("drilldown_query_timeframe"): filters.append({"field": "drilldown_query_timeframe", "operator": "EQ", "value": drilldown_query_timeframe}) if mapping_strategy := args.get("mapping_strategy"): filters.append({"field": "mapping_strategy", "operator": "EQ", "value": mapping_strategy}) if alert_domain := args.get("alert_domain"): filters.append({"field": "alert_domain", "operator": "EQ", "value": alert_domain}) return filters def bioc_list_command(client: Client, args: Dict) -> CommandResults: """ API Docs https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Get-BIOCs Returns a list of BIOCs. Args: client (Client): The client to use. args (Dict): The command arguments. Returns: CommandResults: The command results. """ filters = create_filters_for_bioc_and_correlation_rules(args) page = arg_to_number(args.get("page")) or 0 limit = arg_to_number(args.get("limit")) or 50 page_size = arg_to_number(args.get("page_size")) or limit extended_view = argToBoolean(args.get("extra_data", False)) request_data = assign_params( extended_view=extended_view, search_from=page * page_size, search_to=(page + 1) * page_size, ) request_data["filters"] = filters reply = client.get_biocs({"request_data": request_data}) biocs = reply.get("objects", []) readable_output = tableToMarkdown( name="BIOCs List", t=biocs, headerTransform=string_to_table_header, headers=["rule_id", "name", "type", "severity", "status"], removeNull=True, ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.BIOC", outputs_key_field="rule_id", outputs=biocs, raw_response=reply, ) def bioc_create_or_update_helper(client: Client, args: Dict) -> dict: """ Creates or updates BIOC indicators based on provided arguments. Args: client (Client): The client to use. args (Dict): The command arguments containing rule configuration. Returns: dict: The raw response from the client containing the update/creation results. """ bioc_data = { # required for updating "rule_id": args.get("rule_id"), # required fields "name": args.get("name"), "severity": BIOC_AND_CR_SEVERITY_MAPPING.get(args.get("severity", "")), # not required but need to be null "type": args.get("type"), "is_xql": argToBoolean(args.get("is_xql")) if args.get("is_xql") else None, "comment": args.get("comment"), "status": args.get("status"), "mitre_technique_id_and_name": args.get("mitre_technique_id_and_name") or [], "mitre_tactic_id_and_name": args.get("mitre_tactic_id_and_name") or [], } indicator = args.get("indicator") # required if indicator: try: indicator = json.loads(indicator) bioc_data["indicator"] = indicator except ValueError: raise DemistoException("Unable to parse 'indicator'. Please use the JSON format.") return client.insert_or_update_biocs({"request_data": [bioc_data]}) def bioc_create_command(client: Client, args: Dict) -> CommandResults: """ API Docs https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Insert-or-update-BIOCs Creates a new BIOC. Args: client (Client): The client to use. args (Dict): The command arguments. Returns: CommandResults: The command results. """ reply = bioc_create_or_update_helper(client, args) if added_objects := reply.get("added_objects", []): message = added_objects[0].get("status") outputs = {"rule_id": added_objects[0].get("id")} else: message = "No BIOCs created." outputs = {} return CommandResults( readable_output=message, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.BIOC", outputs_key_field="rule_id", outputs=outputs, raw_response=reply, ) def bioc_update_command(client: Client, args: Dict) -> CommandResults: """ API Docs https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Insert-or-update-BIOCs Updates an existing BIOC. Args: client (Client): The client to use. args (Dict): The command arguments. Returns: CommandResults: The command results. """ reply = bioc_create_or_update_helper(client, args) if updated_objects := reply.get("updated_objects"): message = updated_objects[0].get("status") outputs = {"rule_id": updated_objects[0].get("id")} else: message = "No BIOCs updated." outputs = {} return CommandResults( readable_output=message, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.BIOC", outputs_key_field="rule_id", outputs=outputs, raw_response=reply, ) def bioc_delete_command(client: Client, args: Dict) -> CommandResults: """ API Docs https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Delete-BIOCs Deletes a BIOC. Args: client (Client): The client to use. args (Dict): The command arguments. Returns: str: Success message. """ filters: list = create_filters_for_bioc_and_correlation_rules(args) request_data = {"request_data": {"filters": filters}} res = client.delete_biocs(request_data) rule_ids = res.get("objects", []) count = len(rule_ids) if count == 1: return CommandResults(readable_output=f"BIOC with id {rule_ids[0]} deleted successfully.") elif count > 1: ids_str = ", ".join(map(str, rule_ids)) return CommandResults(readable_output=f"BIOCs with ids {ids_str} deleted successfully.") else: return CommandResults(readable_output="No BIOCs were found to delete.") def correlation_rule_list_command(client: Client, args: Dict) -> CommandResults: """ Returns a list of correlation rules. Args: client (Client): The client to use. args (Dict): The command arguments. Returns: CommandResults: The command results. """ filters = create_filters_for_bioc_and_correlation_rules(args) if filter_json := args.get("filter_json"): try: filter_json = json.loads(filter_json) filters.extend(filter_json) except ValueError: raise DemistoException("Unable to parse 'filter_json'. Please use the JSON format.") page = arg_to_number(args.get("page")) or 0 limit = arg_to_number(args.get("limit")) or 50 page_size = arg_to_number(args.get("page_size")) or limit request_data = assign_params( extended_view=argToBoolean(args.get("extra_data", False)), search_from=page * page_size, search_to=(page + 1) * page_size, ) request_data["filters"] = filters reply = client.get_correlation_rules({"request_data": request_data}) rules = reply.get("objects", []) readable_output = tableToMarkdown( name="Correlation Rules List", t=rules, headers=["rule_id", "name", "severity", "description", "is_enabled"], removeNull=True, headerTransform=string_to_table_header, ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.CorrelationRule", outputs_key_field="rule_id", outputs=rules, raw_response=reply, ) def correlation_rule_create_or_update_helper(client: Client, args: Dict) -> dict: """ Creates or updates correlation rules based on provided arguments. Args: client (Client): The client to use. args (Dict): The command arguments containing rule configuration. Returns: dict: The raw response from the client containing the update/creation results. """ severity_arg = args.get("severity") severity_mapped = BIOC_AND_CR_SEVERITY_MAPPING.get(severity_arg) if severity_arg else None rule_data = { # Required fields "rule_id": args.get("rule_id"), "name": args.get("name"), "severity": severity_mapped, "xql_query": args.get("xql_query"), "is_enabled": argToBoolean(args.get("is_enabled")) if args.get("is_enabled") else None, "action": "ALERTS", "timezone": args.get("timezone"), "dataset": args.get("dataset"), "alert_category": args.get("alert_category", "").upper() if args.get("alert_category") else None, "execution_mode": args.get("execution_mode", "").upper() if args.get("execution_mode") else None, "mapping_strategy": args.get("mapping_strategy", "").upper() if args.get("mapping_strategy") else None, # Use 'or None' to convert empty strings ("") into JSON null. We must put a value for those fields. "description": args.get("description") or None, "alert_name": args.get("alert_name") or None, "alert_description": args.get("alert_description") or None, "search_window": args.get("search_window") or None, "crontab": args.get("schedule_linux") or None, "simple_schedule": args.get("schedule") or None, "drilldown_query_timeframe": args.get("drilldown_query_timeframe") or None, "investigation_query_link": args.get("investigation_query_link") or None, "suppression_enabled": argToBoolean(args.get("suppression_enabled")) if args.get("suppression_enabled") else None, "suppression_duration": args.get("suppression_duration") or None, "suppression_fields": args.get("suppression_fields") or None, # User Defined Severity (Must be None unless Severity is "User Defined") "user_defined_severity": args.get("user_defined_severity") or None, "user_defined_category": args.get("user_defined_category") or None, # Defaults to "{}" string if missing so json.loads doesn't fail "mitre_defs": json.loads(args.get("mitre_defs_json") or "{}"), "alert_fields": json.loads(args.get("alert_fields") or "{}"), } return client.create_or_update_correlation_rules({"request_data": [rule_data]}) def correlation_rule_create_command(client: Client, args: Dict) -> CommandResults: """ API Docs https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Insert-or-update-Correlation-Rules Creates a new correlation rule. Args: client (Client): The client to use. args (Dict): The command arguments. Returns: CommandResults: The command results. """ reply = correlation_rule_create_or_update_helper(client, args) if added_objects := reply.get("added_objects", []): message = added_objects[0].get("status") outputs = {"rule_id": added_objects[0].get("id")} else: message = "No Correlation Rules created." outputs = {} return CommandResults( readable_output=message, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.CorrelationRule", outputs_key_field="rule_id", outputs=outputs, raw_response=reply, ) def correlation_rule_update_command(client: Client, args: Dict) -> CommandResults: """ API Docs https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Insert-or-update-Correlation-Rules Updates an existing correlation rule. Args: client (Client): The client to use. args (Dict): The command arguments. Returns: CommandResults: The command results. """ reply = correlation_rule_create_or_update_helper(client, args) if updated_objects := reply.get("updated_objects"): message = updated_objects[0].get("status") outputs = {"rule_id": updated_objects[0].get("id")} else: message = "No Correlation Rules updated." outputs = {} return CommandResults( readable_output=message, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.CorrelationRule", outputs_key_field="rule_id", outputs=outputs, raw_response=reply, ) def correlation_rule_delete_command(client: Client, args: Dict) -> CommandResults: """ API Docs https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Delete-Correlation-Rules Deletes correlation rules. Args: client (Client): The client to use. args (Dict): The command arguments. Returns: str: Success message. """ rule_ids = argToList(args.get("rule_id")) rule_id_list = [] for rule_id in rule_ids: try: rule_id_list.append({"field": "rule_id", "operator": "EQ", "value": int(rule_id)}) except (ValueError, TypeError): # If rule_id is None, "abc", or "", skip it safely continue reply = client.delete_correlation_rules({"request_data": {"filters": rule_id_list}}) deleted_ids = reply.get("objects", []) objects_count = reply.get("objects_count") if objects_count == 0: status = "Could not find any correlation rules to delete." elif objects_count == 1: status = f"Correlation Rule {deleted_ids[0]} was deleted." else: ids_str = ", ".join(map(str, deleted_ids)) status = f"Correlation Rules {ids_str} were deleted." return CommandResults(readable_output=status, raw_response=reply) def api_key_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: """ API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Get-existing-API-keys Gets a list of existing API keys. Args: client (Client): The Cortex XDR client. args (dict): The command arguments. Returns: CommandResults: The results of the command. """ api_ids = [int(x) for x in argToList(args.get("api_id", []))] or None roles_list = argToList(args.get("role", [])) expires_before = ( arg_to_timestamp(args.get("expires_before"), arg_name="expires_before") if args.get("expires_before") else None ) expires_after = arg_to_timestamp(args.get("expires_after"), arg_name="expires_after") if args.get("expires_after") else None filters = [] if api_ids: filters.append({"field": "id", "operator": "in", "value": api_ids}) if roles_list: filters.append({"field": "roles", "operator": "contains", "value": roles_list}) if expires_before: filters.append({"field": "expiration", "operator": "lte", "value": expires_before}) if expires_after: filters.append({"field": "expiration", "operator": "gte", "value": expires_after}) api_keys = client.get_api_keys({"filters": filters}) readable_output = tableToMarkdown( name="API Keys", t=api_keys, headers=["id", "roles", "created_by", "creation_time", "expiration", "comment"], date_fields=["creation_time", "expiration"], removeNull=True, headerTransform=string_to_table_header, ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.APIKeyData", outputs=api_keys, outputs_key_field="id", raw_response=api_keys, ) def api_key_delete_command(client: Client, args: Dict[str, Any]) -> CommandResults: """ API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Delete-API-keys Deletes the specified API keys. Args: client (Client): The Cortex XDR client. args (dict): The command arguments. Returns: CommandResults: The results of the command. """ api_ids = [int(x) for x in argToList(args.get("api_id", []))] or None request_data = {"filters": [{"field": "id", "operator": "in", "value": api_ids}]} client.delete_api_keys(request_data=request_data) return CommandResults(readable_output="API Keys deleted successfully.") def get_asset_list_command(client: Client, args: Dict) -> CommandResults: """ Returns a list of assets. Parameters: - client (Client): The client to use for the request. - args (dict): The command arguments. Returns: - CommandResults: A CommandResults object containing the assets. """ asset_id_list = argToList(args.get("asset_id", "")) sort_field = args.get("sort_field", "").lower() sort_order = args.get("sort_order", "").upper() filter_json = args.get("filter_json", "") if filter_json: try: filter_json = json.loads(filter_json) except ValueError: raise DemistoException("Unable to parse 'filter_json'. Please use the JSON format.") limit = arg_to_number(args.get("limit")) or 50 page_size = arg_to_number(args.get("page_size")) or limit page = arg_to_number(args.get("page")) or 0 assets = [] if asset_id_list: for asset_id in asset_id_list: assets.extend(client.get_asset(asset_id)) else: request_data: Dict[str, Any] = { "request_data": { "search_from": page * page_size, "search_to": (page + 1) * page_size, } } if filter_json: request_data["request_data"]["filters"] = filter_json if sort_field: request_data["request_data"]["sort"] = [{"FIELD": sort_field, "ORDER": sort_order or "ASC"}] assets = client.list_assets(request_data=request_data) readable_assets = [] for asset in assets: readable_asset = { "ID": asset.get("xdm.asset.id"), "Name": asset.get("xdm.asset.name"), "Critical Cases Count": asset.get("xdm.asset.related_issues.critical_assets"), "Critical Issues Count": asset.get("xdm.asset.related_issues.critical_issues"), } if asset.get("xdm.asset.first_observed"): readable_asset["First Observed"] = timestamp_to_datestring(asset.get("xdm.asset.first_observed")) if asset.get("xdm.asset.last_observed"): readable_asset["Last Observed"] = timestamp_to_datestring(asset.get("xdm.asset.last_observed")) readable_assets.append(readable_asset) readable_output = tableToMarkdown( name="Cortex XDR Assets", t=readable_assets, headers=["ID", "Name", "First Observed", "Last Observed", "Critical Cases Count", "Critical Issues Count"], removeNull=True, ) assets = replace_dots_in_keys(assets) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.Asset", outputs_key_field="xdm_asset_id", outputs=assets, raw_response=assets, ) def get_asset_schema_command(client: Client, args: Dict) -> CommandResults: """ Gets the schema of the asset inventory. Parameters: - client (Client): The client to use for the request. - args (dict): The command arguments (not in use). Returns: - CommandResults: A CommandResults object containing the asset schema. """ schema = client.get_asset_schema() readable_output = tableToMarkdown( name="Cortex XDR Asset Schema", t=schema, headerTransform=string_to_table_header, headers=["field_pretty_name", "field_name", "field_type"], removeNull=True, ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.AssetSchema", outputs=schema, outputs_key_field="field_name", raw_response=schema, ) def get_asset_schema_field_options_command(client: Client, args: Dict) -> CommandResults: """ Gets the enum values of a specified field in the asset schema. Parameters: - client (Client): The client to use for the request. - args (dict): The command arguments. Returns: - CommandResults: A CommandResults object containing the field options. """ field_name = args.get("field_name", "") options = client.get_asset_schema_field_options(field_name) readable_output = tableToMarkdown( name=f"Cortex XDR Asset Schema Options for {field_name}", t=options, headerTransform=string_to_table_header, removeNull=True, ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.AssetSchema", outputs_key_field="field_name", outputs={"field_name": field_name, "options": options}, raw_response=options, ) def create_asset_group_command(client: Client, args: Dict) -> CommandResults: """ Creates an asset group. Parameters: - client (Client): The client to use for the request. - args (dict): The command arguments. Returns: - CommandResults: A CommandResults object containing the created asset group. """ group_name = args.get("group_name", "") group_type = args.get("group_type", "") group_description = args.get("group_description", "") membership_predicate_json = args.get("membership_predicate_json", "") if membership_predicate_json: try: membership_predicate_json = json.loads(membership_predicate_json) except ValueError: raise DemistoException("Unable to parse 'membership_predicate_json'. Please use the JSON format.") update_data = assign_params( group_name=group_name, group_type=group_type, group_description=group_description, ) request_data = {"request_data": {"asset_group": update_data}} if membership_predicate_json: request_data["request_data"]["asset_group"]["membership_predicate"] = membership_predicate_json res = client.create_asset_group(request_data=request_data) return CommandResults(readable_output="Asset group created successfully", raw_response=res) def delete_asset_group_command(client: Client, args: Dict) -> CommandResults: """ Deletes an asset group. Parameters: - client (Client): The client to use for the request. - args (dict): The command arguments. Returns: - CommandResults: A CommandResults object. """ group_id = args.get("group_id", "") client.delete_asset_group(group_id) return CommandResults(readable_output="Asset group deleted successfully.") def list_asset_groups_command(client: Client, args: Dict) -> CommandResults: """ Returns a list of asset groups. Parameters: - client (Client): The client to use for the request. - args (dict): The command arguments. Returns: - CommandResults: A CommandResults object containing the asset groups. """ sort_field = args.get("sort_field", "").upper() sort_order = args.get("sort_order", "").upper() filter_json = args.get("filter_json", "") if filter_json: try: filter_json = json.loads(filter_json) except ValueError: raise DemistoException("Unable to parse 'filter_json'. Please use the JSON format.") limit = arg_to_number(args.get("limit")) or 50 page_size = arg_to_number(args.get("page_size")) or limit page = arg_to_number(args.get("page")) or 0 request_data: Dict[str, Any] = { "request_data": { "search_from": page * page_size, "search_to": (page + 1) * page_size, } } if filter_json: request_data["request_data"]["filters"] = filter_json if sort_field: request_data["request_data"]["sort"] = [{"FIELD": sort_field, "ORDER": sort_order or "ASC"}] groups = client.list_asset_groups(request_data=request_data) readable_groups = [] for group in groups: readable_asset = { "ID": group.get("XDM.ASSET_GROUP.ID"), "Name": group.get("XDM.ASSET_GROUP.NAME"), "Type": group.get("XDM.ASSET_GROUP.TYPE"), "Description": group.get("XDM.ASSET_GROUP.DESCRIPTION"), } readable_groups.append(readable_asset) readable_output = tableToMarkdown( name="Cortex XDR Asset Groups", t=readable_groups, headers=["ID", "Name", "Type", "Description"], headerTransform=string_to_table_header, removeNull=True, ) groups = replace_dots_in_keys(groups) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.AssetGroup", outputs_key_field="XDM_ASSET_GROUP_ID", outputs=groups, raw_response=groups, ) def update_asset_group_command(client: Client, args: Dict) -> CommandResults: """ Updates an asset group. Parameters: - client (Client): The client to use for the request. - args (dict): The command arguments. Returns: - CommandResults: A CommandResults object. """ group_id = args.get("group_id", "") group_name = args.get("group_name", "") group_type = args.get("group_type", "") group_description = args.get("group_description", "") membership_predicate_json = args.get("membership_predicate_json", "") if membership_predicate_json: try: membership_predicate_json = json.loads(membership_predicate_json) except ValueError: raise DemistoException("Unable to parse 'membership_predicate_json'. Please use the JSON format.") update_data = assign_params( group_name=group_name, group_type=group_type, group_description=group_description, membership_predicate=membership_predicate_json, ) request_data = {"request_data": {"asset_group": update_data}} client.update_asset_group(group_id, request_data=request_data) return CommandResults(readable_output="Asset group updated successfully") def get_vulnerability_details_command(client: Client, args: Dict) -> CommandResults: """ API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Vulnerabilities Gets vulnerability details by ID. Args: client (Client): The Cortex XDR client. args (Dict): The command arguments. Returns: CommandResults: The command results. """ vulnerability_id = args.get("vulnerability_id", "") response = client.get_vulnerability_details(vulnerability_id) hr_data = { "Vulnerability ID": response.get("vulnerabilityID"), "Description": response.get("description"), "Score": response.get("cvss", {}).get("score"), "Publish Date": arg_to_timestamp(response.get("publishedDate"), "publishedDate") if response.get("publishedDate") else None, } readable_output = tableToMarkdown( name="Vulnerability Details", t=hr_data, headers=["Vulnerability ID", "Description", "Score", "Publish Date"], removeNull=True, ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.Vulnerability", outputs_key_field="vulnerabilityID", outputs=response, raw_response=response, ) def endpoint_triage_preset_list_command(client: Client) -> CommandResults: """ API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Get-triage-presets Gets triage presets. Args: client (Client): The Cortex XDR client. Returns: CommandResults: The command results. """ presets: list = client.get_triage_presets() readable_output = tableToMarkdown( name="Endpoint Triage Presets", t=presets, headers=["name", "uuid", "os", "type", "created_by", "description"], headerTransform=string_to_table_header, removeNull=True, ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.EndpointTriagePreset", outputs=presets, outputs_key_field="uuid", raw_response=presets, ) def healthcheck_run_command(client: Client) -> CommandResults: """ API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/System-Health-Check Runs a system health check. Args: client (Client): The Cortex XDR client. Returns: CommandResults: The command results. """ response = client.run_healthcheck() status = response.get("status", "unknown") return CommandResults( readable_output=f"**Cortex XDR health status: {status}**", outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.HealthStatus", outputs=response, raw_response=response, ) def endpoint_triage_command(client: Client, args: Dict) -> CommandResults: """ API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Initiate-Forensics-Triage Initiates forensics triage on endpoints. Args: client (Client): The Cortex XDR client. args (Dict): The command arguments. Returns: CommandResults: The command results. """ agent_ids = argToList(args.get("endpoint_id")) collector_uuid = args.get("collector_uuid") request_data: Dict[str, Any] = {"agent_ids": agent_ids} if collector_uuid: request_data["collector_uuid"] = collector_uuid raw_response = client.triage_endpoint({"request_data": request_data}) readable_output = tableToMarkdown( name="Triage Endpoint Results", t=raw_response, headers=["TRIAGE_ID", "SUCCESSFUL_AGENT_IDS", "UNSUCCESSFUL_AGENT_IDS"], headerTransform=string_to_table_header, removeNull=True, ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.EndpointTriage", outputs=raw_response, outputs_key_field="EndpointTriage", raw_response=raw_response, ) def automation_script_create_command(client: Client, args: Dict) -> CommandResults: """ Creates or updates an automation script by uploading a file. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Insert-or-update-a-script Args: client (Client): The Cortex XDR client. args (dict): The command arguments. Returns: CommandResults: The results of the command. """ entry_id = args.get("entry_id") file_info = demisto.getFilePath(entry_id) file_path = file_info.get("path", "") file_name = file_info.get("name", "") demisto.debug(f"Got file info {file_info}") with open(file_path, "rb") as f: file_content = f.read() files = {"file": (file_name, file_content)} client.create_automation_script(files) return CommandResults(readable_output="Automation script created successfully.") def automation_script_get_command(client: Client, args: Dict) -> dict: """ Gets an automation script and returns it as a file. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Get-a-script Args: client (Client): The Cortex XDR client. args (dict): The command arguments. Returns: dict: A file result dictionary. """ field = args.get("field", "") value = args.get("value", "") request_data = {"request_data": {"filter": {"field": field, "value": value}}} file_content = client.get_automation_script(request_data) return fileResult(filename=f"automation_script_{value}", data=file_content) def automation_script_delete_command(client: Client, args: Dict) -> CommandResults: """ Deletes an automation script. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Delete-API-keys Args: client (Client): The Cortex XDR client. args (dict): The command arguments. Returns: CommandResults: The results of the command. """ field = args.get("field", "") value = args.get("value", "") request_data = {"request_data": {"filter": {"field": field, "value": value}}} client.delete_automation_script(request_data) return CommandResults(readable_output="Automation script deleted successfully.") def automation_playbook_create_command(client: Client, args: Dict) -> CommandResults: """ Creates or updates an automation playbook by uploading a file. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Insert-or-update-playbooks Args: client (Client): The Cortex XDR client. args (dict): The command arguments. Returns: CommandResults: The results of the command. """ entry_id = args.get("entry_id") file_info = demisto.getFilePath(entry_id) demisto.debug(f"Got file info {file_info}") file_path = file_info.get("path", "") file_name = file_info.get("name", "") with open(file_path, "rb") as f: file_content = f.read() files = {"file": (file_name, file_content)} client.create_automation_playbook(files) return CommandResults(readable_output="Automation playbook created successfully.") def automation_playbook_get_command(client: Client, args: Dict) -> dict: """ Gets an automation playbook and returns it as a file. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Get-a-playbook Args: client (Client): The Cortex XDR client. args (dict): The command arguments. Returns: dict: A file result dictionary. """ field = args.get("field", "") value = args.get("value", "") request_data = {"request_data": {"filter": {"field": field, "value": value}}} file_content = client.get_automation_playbook(request_data) return fileResult(filename=f"automation_playbook_{value}", data=file_content) def automation_playbook_delete_command(client: Client, args: Dict) -> CommandResults: """ Deletes an automation playbook. API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Delete-a-playbook Args: client (Client): The Cortex XDR client. args (dict): The command arguments. Returns: CommandResults: The results of the command. """ field = args.get("field", "") value = args.get("value", "") request_data = {"request_data": {"filter": {"field": field, "value": value}}} client.delete_automation_playbook(request_data) return CommandResults(readable_output="Automation playbook deleted successfully.") def normalize_case_data_record(incident_record: Dict[str, Any]) -> Dict[str, Any]: """ Normalizes a single record returned by the get_multiple_incidents_extra_data endpoint into the case-shaped output used by the xdr-case-list command. Args: - incident_record (dict): A single record from the endpoint, of the form {"incident": {...}, "alerts": {...}, "file_artifacts": {...}, "network_artifacts": {...}}. Flat records (without an "incident" wrapper) are also supported. Returns: - dict: The normalized case record. """ incident = incident_record.get("incident", incident_record) case: dict[str, Any] = {} for field, value in incident.items(): case[INCIDENT_TO_CASE_FIELD_MAP.get(field, field)] = value case_id = case.get("case_id") nested_data_map = { "alerts": "Issues", "file_artifacts": "FileArtifacts", "network_artifacts": "NetworkArtifacts", } for source_key, case_key in nested_data_map.items(): records = dict_safe_get(incident_record, [source_key, "data"], default_return_value=[], return_type=list) if records: for record in records: record.setdefault("case_id", case_id) case[case_key] = records return case def case_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: """ API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Retrieve-cases-based-on-filters Returns a list of cases. Args: - client (Client): The client to use for the request. - args (dict): The command arguments. Returns: - CommandResults: A CommandResults object. """ case_ids = argToList(args.get("case_id")) case_domains = argToList(args.get("case_domain")) severities = argToList(args.get("severity")) statuses = argToList(args.get("status")) created_before = arg_to_timestamp(args.get("created_before"), "created_before") if args.get("created_before") else None created_after = arg_to_timestamp(args.get("created_after"), "created_after") if args.get("created_after") else None sort_field = args.get("sort_field") sort_order = args.get("sort_order") page = arg_to_number(args.get("page")) page_size = arg_to_number(args.get("page_size")) manual_pagination = page is not None or page_size is not None limit = arg_to_number(args.get("limit")) or 50 if manual_pagination: page = page or 0 page_size = page_size or limit search_from = page * page_size search_to = (page + 1) * page_size else: search_from = 0 search_to = limit extra_data = argToBoolean(args.get("extra_data", False)) if extra_data: return case_list_with_extra_data( client=client, case_ids=case_ids, statuses=statuses, created_after=created_after, created_before=created_before, sort_field=sort_field, sort_order=sort_order, search_from=search_from, search_to=search_to, ) filters = [] if case_ids: try: converted_ids = list(map(int, case_ids)) filters.append({"field": "case_id", "operator": "in", "value": converted_ids}) except ValueError: raise DemistoException(f"Invalid case IDs: {case_ids}. Case IDs must be a comma-separated list of integers.") if case_domains: filters.append({"field": "case_domain", "operator": "in", "value": case_domains}) if severities: filters.append({"field": "severity", "operator": "in", "value": severities}) if statuses: filters.append({"field": "status_progress", "operator": "in", "value": statuses}) if created_before: filters.append({"field": "creation_time", "operator": "lte", "value": created_before}) if created_after: filters.append({"field": "creation_time", "operator": "gte", "value": created_after}) request_data = { "search_from": search_from, "search_to": search_to, "filters": filters, } if sort_field: request_data["sort"] = {"field": sort_field, "keyword": sort_order or "desc"} else: request_data["sort"] = {} cases = client.search_cases({"request_data": request_data}) readable_output = tableToMarkdown( name="Cortex XDR Cases", t=cases, headers=["case_id", "case_name", "case_domain", "creation_time", "modification_time", "description"], date_fields=["creation_time", "modification_time"], headerTransform=string_to_table_header, removeNull=True, ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.Case", outputs_key_field="case_id", outputs=cases, raw_response=cases, ) def case_list_with_extra_data( client: Client, case_ids: List[str], statuses: List[str], created_after: Optional[Union[int, float]], created_before: Optional[Union[int, float]], sort_field: Optional[str], sort_order: Optional[str], search_from: int, search_to: int, ) -> CommandResults: mapped_sort_field = { "case_id": "incident_id", "creation_time": "creation_time", }.get(sort_field or "") raw_records = client.get_multiple_incidents_extra_data( exclude_artifacts=False, incident_id_list=case_ids, statuses=statuses, gte_creation_time_milliseconds=arg_to_number(created_after) or 0, lte_creation_time_milliseconds=arg_to_number(created_before) or 0, sort_field=mapped_sort_field, sort_order=sort_order, search_from=search_from, limit=search_to, ) cases = [normalize_case_data_record(record) for record in raw_records] readable_output = tableToMarkdown( name="Cortex XDR Cases", t=cases, headers=["case_id", "case_name", "case_domain", "creation_time", "modification_time", "description"], date_fields=["creation_time", "modification_time"], headerTransform=string_to_table_header, removeNull=True, ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.Case", outputs_key_field="case_id", outputs=cases, raw_response=raw_records, ) def case_update_command(client: Client, args: Dict[str, Any]) -> CommandResults: """ API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Update-existing-case Updates an existing case via the public_api/v1/case/update/{case-id} endpoint. Maps user-friendly argument values to the exact API strings and enforces the API's conditional rules client-side: - resolve_reason / resolve_comment are only valid when status is "Resolved". - resolving (status "Resolved") requires a resolve_reason. - at least one valid field must be sent (an empty update_data returns 400). Args: - client (Client): The client to use for the request. - args (dict): The command arguments. Returns: - CommandResults: A CommandResults object. """ # Maps friendly status inputs to the exact API strings expected by status_progress. status_mapper = { "new": "New", "in_progress": "In Progress", "in progress": "In Progress", "under_investigation": "In Progress", "resolved": "Resolved", } # Maps snake_case resolve reasons to the exact API strings (all six supported). resolve_reason_mapper = { "resolved_known_issue": "Resolved - Known Issue", "resolved_duplicate": "Resolved - Duplicate Case", "resolved_false_positive": "Resolved - False Positive", "resolved_true_positive": "Resolved - True Positive", "resolved_security_testing": "Resolved - Security Testing", "resolved_other": "Resolved - Other", } case_id = args.get("case_id", "") # required status_arg = args.get("status", "") if status_arg: status = status_mapper.get(status_arg.strip().lower()) if not status: raise DemistoException(f"Invalid status '{status_arg}'. Supported values are: New, In Progress, Resolved.") else: status = None resolve_reason_arg = args.get("resolve_reason") if resolve_reason_arg: resolve_reason = resolve_reason_mapper.get(resolve_reason_arg.strip().lower()) if not resolve_reason: raise DemistoException( f"Invalid resolve_reason '{resolve_reason_arg}'. Supported values are: " f"{', '.join(sorted(resolve_reason_mapper))}." ) else: resolve_reason = None resolve_comment = args.get("resolve_comment") user_severity = args.get("user_severity") assigned_user = args.get("assigned_user") notes = args.get("notes") custom_fields_arg = args.get("custom_fields") is_resolving = status == "Resolved" # Enforce the API's conditional rules client-side with clear error messages. if (resolve_reason or resolve_comment) and not is_resolving: raise DemistoException( "The 'resolve_reason' and 'resolve_comment' arguments can only be provided when 'status' is set to 'Resolved'." ) if is_resolving and not resolve_reason: raise DemistoException("The 'resolve_reason' argument is required when resolving a case (status 'Resolved').") # assign_params drops None / empty values, which keeps null values out of the payload. update_data = assign_params( status_progress=status, resolve_reason=resolve_reason, resolve_comment=resolve_comment, assigned_user=assigned_user, notes=notes, ) # user_severity must allow an explicit empty string "" (used to clear the severity), # so it is handled separately to avoid being dropped by assign_params. if user_severity is not None: update_data["user_severity"] = user_severity # custom_fields lets users send tenant-defined fields directly inside update_data. # We only validate that the input is a valid JSON object (a dict); field names/values # are the user's responsibility and are NOT validated by the integration. if custom_fields_arg is not None: try: parsed_custom_fields = json.loads(custom_fields_arg) except (ValueError, TypeError): raise DemistoException("The 'custom_fields' argument must be a valid JSON object.") if not isinstance(parsed_custom_fields, dict): raise DemistoException("The 'custom_fields' argument must be a valid JSON object.") # Standard documented fields are authoritative: skip any custom_fields key that # collides with a standard field already set in update_data (no silent override). for key, value in parsed_custom_fields.items(): if key in update_data: continue update_data[key] = value if not update_data: raise DemistoException( "No fields to update were provided. Provide at least one of: status, resolve_reason, " "resolve_comment, user_severity, assigned_user, notes, custom_fields." ) client.update_case(case_id, request_data={"request_data": {"update_data": update_data}}) return CommandResults(readable_output=f"Case {case_id} updated successfully") def case_artifact_list_command(client: Client, args: Dict[str, Any]) -> List[CommandResults]: """ API Docs: https://docs-cortex.paloaltonetworks.com/r/Cortex-XDR-Platform-APIs/Retrieve-Case-Artifacts-by-Case-Id Retrieves artifacts for a specific case. Args: - client (Client): The client to use for the request. - args (dict): The command arguments. Returns: - List[CommandResults]: A list of CommandResults objects. """ case_id = args.get("case_id", "") artifacts = client.get_case_artifacts(case_id) if isinstance(artifacts, list) and len(artifacts) > 0: artifacts = artifacts[0] network_artifacts = artifacts.get("network_artifacts", {}).get("DATA", []) file_artifacts = artifacts.get("file_artifacts", {}).get("DATA", []) command_results = [] if network_artifacts: command_results.append( CommandResults( readable_output=tableToMarkdown( name=f"Network Artifacts for Case {case_id}", t=network_artifacts, headerTransform=string_to_table_header, removeNull=True, ), outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.CaseNetworkArtifact", outputs=network_artifacts, raw_response=network_artifacts, ) ) if file_artifacts: command_results.append( CommandResults( readable_output=tableToMarkdown( name=f"File Artifacts for Case {case_id}", t=file_artifacts, headerTransform=string_to_table_header, removeNull=True, ), outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.CaseFileArtifact", outputs=file_artifacts, raw_response=file_artifacts, ) ) if not command_results: command_results.append(CommandResults(readable_output=f"No artifacts found for case {case_id}")) return command_results def list_issues_command(client: Client, args: Dict) -> CommandResults: """ Returns a list of issues. Parameters: - client (Client): The client to use for the request. - args (dict): The command arguments. Returns: - CommandResults: A CommandResults object containing the issues. """ # Issues with an 'INFO' severity level are filtered out and will not be displayed in the UI filters = [] if issue_ids := argToList(args.get("issue_id")): try: converted_ids = [int(i) for i in issue_ids] filters.append({"field": "id", "operator": "in", "value": converted_ids}) except (ValueError, TypeError): raise DemistoException("Invalid Issue ID provided. Please ensure all IDs are numbers.") filter_mappings = { "external_id": "external_id", "detection_method": "detection.method", "domain": "issue_domain", "severity": "severity", } for arg_name, api_field in filter_mappings.items(): if values := argToList(args.get(arg_name)): filters.append({"field": api_field, "operator": "in", "value": values}) if insert_time := args.get("insert_time"): timestamp = arg_to_timestamp(insert_time, arg_name="insert_time") filters.append({"field": "_insert_time", "operator": "gte", "value": timestamp}) if status := argToList(args.get("status")): mapped_statuses = [ISSUE_STATUSES_MAP.get(s) for s in status if s in ISSUE_STATUSES_MAP] filters.append({"field": "status.progress", "operator": "in", "value": mapped_statuses}) limit = arg_to_number(args.get("limit")) or 50 page_size = arg_to_number(args.get("page_size")) or limit page = arg_to_number(args.get("page")) or 0 request_data: Dict[str, Any] = { "request_data": { "search_from": page * page_size, "search_to": (page + 1) * page_size, } } if filters: request_data["request_data"]["filters"] = filters if sort_field := args.get("sort_field"): sort_order = args.get("sort_order", "asc").lower() if sort_field == "issue_id": # converting issue_id to id as the api expects sort_field = "id" request_data["request_data"]["sort"] = {"field": sort_field, "keyword": sort_order} request_data["request_data"]["include_fields"] = ["custom_fields", "normalized_fields"] issues = client.list_issues(request_data) hr_issues = [ { "ID": issue.get("id"), "Name": issue.get("name"), "Type": issue.get("type"), "Severity": issue.get("severity"), "Status": issue.get("status.progress"), "Description": issue.get("description"), } for issue in issues ] readable_output = tableToMarkdown( name="Issues", t=hr_issues, headers=["ID", "Name", "Type", "Severity", "Status", "Description"], removeNull=True, ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.Issue", outputs_key_field="id", outputs=issues, raw_response=issues, ) def create_issue_command(client: Client, args: Dict) -> CommandResults: """ Creates a new issue. Parameters: - client (Client): The client to use for the request. - args (dict): The command arguments. Returns: - CommandResults: A CommandResults object containing the created issue. """ # Issues with an 'INFO' severity level are filtered out and will not be displayed in the UI issue_data = { # Required "name": args.get("name"), "description": args.get("description"), "observation_time": arg_to_timestamp(args.get("observation_time"), arg_name="observation_time"), "issue_domain": args.get("domain"), "category": args.get("category"), "severity": args["severity"].upper(), # Optional "asset_ids": argToList(args.get("asset_id")), "mitre_tactic": argToList(args.get("mitre_tactic")), "mitre_technique": argToList(args.get("mitre_technique")), "type": args.get("type"), "extended_description": args.get("extended_description"), "impact": args.get("impact"), "tags": args.get("tags"), "is_excluded": argToBoolean(args.get("is_excluded")) if args.get("is_excluded") is not None else None, "is_starred": argToBoolean(args.get("is_starred")) if args.get("is_starred") is not None else None, "assigned_to": args.get("assigned_to"), "assigned_to_pretty": args.get("assigned_to_pretty"), } for field in ["normalized_fields_json", "custom_fields_json"]: field_json = args.get(field) try: issue_data[field] = json.loads(field_json) if field_json else {} except (ValueError, TypeError): raise DemistoException(f"Invalid JSON format in field: {field}") result = client.create_issue({"request_data": {"issue": issue_data}}) readable_output = tableToMarkdown(name="Created Issue", t=result, headerTransform=string_to_table_header, removeNull=True) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.Issue", outputs_key_field="external_id", outputs=result, raw_response=result, ) def update_issue_command(client: Client, args: Dict) -> CommandResults: """ Updates an existing issue. Parameters: - client (Client): The client to use for the request. - args (dict): The command arguments. Returns: - CommandResults: A CommandResults object. """ update_data = assign_params( severity=args["severity"].upper() if args.get("severity") else None, ) if status := ISSUE_STATUSES_MAP.get(args.get("status", "")): update_data["status"] = status if resolution_reason := ISSUE_REASON_MAP.get(args.get("resolve_reason", "")): update_data["status_resolution_reason"] = resolution_reason if resolution_comment := args.get("resolve_comment"): update_data["status_resolution_comment"] = resolution_comment issue_id = args.get("issue_id", "") if not str(issue_id).isdigit(): raise DemistoException(f"'{issue_id}' is not a valid numeric Issue ID.") request_data = {"request_data": {"update_data": update_data}} client.update_issue(issue_id, request_data) return CommandResults(readable_output=f"Issue with ID {issue_id} updated successfully") def main(): # pragma: no cover """ Executes an integration command """ command = demisto.command() params = demisto.params() LOG(f"Command being called is {command}") # using two different credentials object as they both fields need to be encrypted first_fetch_time = params.get("fetch_time", "3 days") base_url = urljoin(params.get("url"), "/public_api/v1") proxy = params.get("proxy") verify_cert = not params.get("insecure", False) statuses = params.get("status") starred = True if params.get("starred") else None starred_incidents_fetch_window = params.get("starred_incidents_fetch_window", "3 days") exclude_artifacts = argToBoolean(params.get("exclude_fields", True)) excluded_alert_fields = argToList(params.get("excluded_alert_fields")) excluded_alert_fields, remove_nulls_from_alerts = handle_excluded_data_from_alerts_param(excluded_alert_fields) xdr_delay = arg_to_number(params.get("xdr_delay")) or 1 try: timeout = int(params.get("timeout", 120)) except ValueError as e: demisto.debug(f"Failed casting timeout parameter to int, falling back to 120 - {e}") timeout = 120 try: max_fetch = int(params.get("max_fetch", 10)) except ValueError as e: demisto.debug(f"Failed casting max fetch parameter to int, falling back to 10 - {e}") max_fetch = 10 client = Client(base_url=base_url, proxy=proxy, verify=verify_cert, timeout=timeout, params=params) args = demisto.args() args["integration_context_brand"] = INTEGRATION_CONTEXT_BRAND args["integration_name"] = INTEGRATION_NAME try: if command == "test-module": client.test_module(first_fetch_time) demisto.results("ok") elif command == "fetch-incidents": integration_instance = demisto.integrationInstance() last_run = demisto.getLastRun().get("next_run", {}) demisto.debug(f"Before starting a new cycle of fetch incidents\n{last_run=}\n{integration_instance=}") next_run, incidents = fetch_incidents( client=client, first_fetch_time=first_fetch_time, integration_instance=integration_instance, exclude_artifacts=exclude_artifacts, last_run=last_run, max_fetch=max_fetch, statuses=statuses, starred=starred, starred_incidents_fetch_window=starred_incidents_fetch_window, excluded_alert_fields=excluded_alert_fields, remove_nulls_from_alerts=remove_nulls_from_alerts, ) demisto.debug(f"Finished a fetch incidents cycle, {next_run=}.Fetched {len(incidents)} incidents.") # demisto.debug(f"{incidents=}") # uncomment to debug, otherwise spams the log last_run_obj = demisto.getLastRun() last_run_obj["next_run"] = next_run demisto.debug(f"full next run: {last_run_obj=}") demisto.setLastRun(last_run_obj) demisto.incidents(incidents) elif command == "xdr-get-incidents": # This command is Deprecated return_outputs(*get_incidents_command(client, args)) elif command == "xdr-asset-list": return_results(get_asset_list_command(client, args)) elif command == "xdr-asset-schema-get": return_results(get_asset_schema_command(client, args)) elif command == "xdr-asset-schema-field-options-get": return_results(get_asset_schema_field_options_command(client, args)) elif command == "xdr-asset-group-create": return_results(create_asset_group_command(client, args)) elif command == "xdr-asset-group-delete": return_results(delete_asset_group_command(client, args)) elif command == "xdr-asset-group-list": return_results(list_asset_groups_command(client, args)) elif command == "xdr-asset-group-update": return_results(update_asset_group_command(client, args)) elif command == "xdr-get-incident-extra-data": return_outputs(*get_incident_extra_data_command(client, args)) elif command == "xdr-update-incident": # This command is Deprecated return_outputs(*update_incident_command(client, args)) elif command == "xdr-get-endpoints": return_results(get_endpoints_command(client, args)) elif command == "xdr-endpoint-alias-change": return_results(endpoint_alias_change_command(client, **args)) elif command == "xdr-insert-parsed-alert": return_outputs(*insert_parsed_alert_command(client, args)) elif command == "xdr-insert-cef-alerts": return_outputs(*insert_cef_alerts_command(client, args)) elif command == "xdr-isolate-endpoint": return_results(isolate_endpoint_command(client, args)) elif command == "xdr-endpoint-isolate": polling_args = {**args, "endpoint_id_list": args.get("endpoint_id")} return_results( run_polling_command( client=client, args=polling_args, cmd="xdr-endpoint-isolate", command_function=isolate_endpoint_command, command_decision_field="action_id", results_function=get_endpoints_command, polling_field="is_isolated", polling_value=["AGENT_ISOLATED"], stop_polling=True, ) ) elif command == "xdr-unisolate-endpoint": return_results(unisolate_endpoint_command(client, args)) elif command == "xdr-endpoint-unisolate": polling_args = {**args, "endpoint_id_list": args.get("endpoint_id")} return_results( run_polling_command( client=client, args=polling_args, cmd="xdr-endpoint-unisolate", command_function=unisolate_endpoint_command, command_decision_field="action_id", results_function=get_endpoints_command, polling_field="is_isolated", polling_value=[ "AGENT_UNISOLATED", "CANCELLED", "ֿPENDING_ABORT", "ABORTED", "EXPIRED", "COMPLETED_PARTIAL", "COMPLETED_SUCCESSFULLY", "FAILED", "TIMEOUT", ], stop_polling=True, ) ) elif command == "xdr-get-distribution-url": return_results(get_distribution_url_command(client, args)) elif command == "xdr-get-create-distribution-status": return_outputs(*get_distribution_status_command(client, args)) elif command == "xdr-get-distribution-versions": return_outputs(*get_distribution_versions_command(client, args)) elif command == "xdr-create-distribution": return_outputs(*create_distribution_command(client, args)) elif command == "xdr-get-audit-management-logs": return_outputs(*get_audit_management_logs_command(client, args)) elif command == "xdr-get-audit-agent-reports": return_outputs(*get_audit_agent_reports_command(client, args)) elif command == "xdr-quarantine-files": return_results(quarantine_files_command(client, args)) elif command == "xdr-file-quarantine": return_results( run_polling_command( client=client, args=args, cmd="xdr-file-quarantine", command_function=quarantine_files_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "core-quarantine-files": polling_args = {**args, "endpoint_id": argToList(args.get("endpoint_id_list"))[0]} return_results( run_polling_command( client=client, args=polling_args, cmd="core-quarantine-files", command_function=quarantine_files_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "xdr-get-quarantine-status": return_results(get_quarantine_status_command(client, args)) elif command == "xdr-restore-file": return_results(restore_file_command(client, args)) elif command == "xdr-file-restore": return_results( run_polling_command( client=client, args=args, cmd="xdr-file-restore", command_function=restore_file_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "xdr-endpoint-scan": return_results(endpoint_scan_command(client, args)) elif command == "xdr-endpoint-scan-execute": return_results( run_polling_command( client=client, args=args, cmd="xdr-endpoint-scan-execute", command_function=endpoint_scan_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "xdr-endpoint-scan-abort": return_results(endpoint_scan_abort_command(client, args)) elif command == "get-mapping-fields": return_results(get_mapping_fields_command()) elif command == "get-remote-data": return_results(get_remote_data_command(client, args, excluded_alert_fields, remove_nulls_from_alerts)) elif command == "update-remote-system": return_results(update_remote_system_command(client, args)) elif command == "xdr-delete-endpoints": return_outputs(*delete_endpoints_command(client, args)) elif command == "xdr-get-policy": return_outputs(*get_policy_command(client, args)) elif command == "xdr-get-endpoint-device-control-violations": return_outputs(*get_endpoint_device_control_violations_command(client, args)) elif command == "xdr-retrieve-files": return_results(retrieve_files_command(client, args)) elif command == "xdr-file-retrieve": polling = run_polling_command( client=client, args=args, cmd="xdr-file-retrieve", command_function=retrieve_files_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) raw = polling.raw_response # raw is the response returned by the get-action-status if polling.scheduled_command: return_results(polling) return status = raw[0].get("status") # type: ignore if status == "COMPLETED_SUCCESSFULLY": file_details_results(client, args, True) else: # status is not in polling value and operation was not COMPLETED_SUCCESSFULLY polling.outputs_prefix = ( f'{args.get("integration_context_brand", "CoreApiModule")}.RetrievedFiles(val.action_id == obj.action_id)' ) return_results(polling) elif command == "xdr-retrieve-file-details": file_details_results(client, args, False) elif command == "xdr-get-scripts": return_outputs(*get_scripts_command(client, args)) elif command == "xdr-get-script-metadata": return_outputs(*get_script_metadata_command(client, args)) elif command == "xdr-get-script-code": return_outputs(*get_script_code_command(client, args)) elif command == "xdr-action-status-get": return_results(action_status_get_command(client, args)) elif command == "get-modified-remote-data": last_run_mirroring: Dict[Any, Any] = get_last_mirror_run() or {} demisto.debug(f"before get-modified-remote-data, last run={last_run_mirroring}") modified_incidents, next_mirroring_time = get_modified_remote_data_command( client=client, args=demisto.args(), mirroring_last_update=last_run_mirroring.get("mirroring_last_update", ""), xdr_delay=xdr_delay, ) last_run_mirroring["mirroring_last_update"] = next_mirroring_time set_last_mirror_run(last_run_mirroring) demisto.debug(f"after get-modified-remote-data, last run={last_run_mirroring}") demisto.debug(f"IDs of modified remote incidents {modified_incidents.modified_incident_ids=}") return_results(modified_incidents) elif command == "xdr-script-run": # used with polling = true always return_results(script_run_polling_command(args, client)) elif command == "xdr-run-script": return_results(run_script_command(client, args)) elif command == "xdr-run-snippet-code-script": return_results(run_snippet_code_script_command(client, args)) elif command == "xdr-snippet-code-script-execute": return_results( run_polling_command( client=client, args=args, cmd="xdr-snippet-code-script-execute", command_function=run_snippet_code_script_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "xdr-get-script-execution-status": return_results(get_script_execution_status_command(client, args)) elif command == "xdr-get-script-execution-results": return_results(get_script_execution_results_command(client, args)) elif command == "xdr-get-script-execution-result-files": return_results(get_script_execution_result_files_command(client, args)) elif command == "xdr-get-cloud-original-alerts": return_results(get_original_alerts_command(client, args)) elif command == "xdr-get-alerts": # This command is Deprecated, use xdr-issue-list instead. return_results(get_alerts_by_filter_command(client, args)) elif command == "xdr-run-script-execute-commands": return_results(run_script_execute_commands_command(client, args)) elif command == "xdr-script-commands-execute": return_results( run_polling_command( client=client, args=args, cmd="xdr-script-commands-execute", command_function=run_script_execute_commands_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "xdr-run-script-delete-file": return_results(run_script_delete_file_command(client, args)) elif command == "xdr-file-delete-script-execute": return_results( run_polling_command( client=client, args=args, cmd="xdr-file-delete-script-execute", command_function=run_script_delete_file_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "xdr-run-script-file-exists": return_results(run_script_file_exists_command(client, args)) elif command == "xdr-file-exist-script-execute": return_results( run_polling_command( client=client, args=args, cmd="xdr-file-exist-script-execute", command_function=run_script_file_exists_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "xdr-run-script-kill-process": return_results((client, args)) elif command == "xdr-kill-process-script-execute": return_results( run_polling_command( client=client, args=args, cmd="xdr-kill-process-script-execute", command_function=run_script_kill_process_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "endpoint": return_results(endpoint_command(client, args)) elif command == "xdr-get-endpoints-by-status": return_results(get_endpoints_by_status_command(client, args)) elif command == "xdr-blocklist-files": return_results(blocklist_files_command(client, args)) elif command == "xdr-blacklist-files": args["prefix"] = "blacklist" return_results(blocklist_files_command(client, args)) elif command == "xdr-allowlist-files": return_results(allowlist_files_command(client, args)) elif command == "xdr-whitelist-files": args["prefix"] = "whitelist" return_results(allowlist_files_command(client, args)) elif command == "xdr-remove-blocklist-files": return_results(remove_blocklist_files_command(client, args)) elif command == "xdr-remove-allowlist-files": return_results(remove_allowlist_files_command(client, args)) elif command == "xdr-get-contributing-event": return_results(get_contributing_event_command(client, args)) elif command == "xdr-replace-featured-field": return_results(replace_featured_field_command(client, args)) elif command == "xdr-endpoint-tag-add": return_results(add_tag_to_endpoints_command(client, args)) elif command == "xdr-endpoint-tag-remove": return_results(remove_tag_from_endpoints_command(client, args)) elif command == "xdr-get-tenant-info": return_results(get_tenant_info_command(client)) elif command == "xdr-list-users": return_results(list_users_command(client, args)) elif command == "xdr-list-risky-users": return_results(list_risky_users_or_host_command(client, "user", args)) elif command == "xdr-list-risky-hosts": return_results(list_risky_users_or_host_command(client, "host", args)) elif command == "xdr-list-user-groups": return_results(list_user_groups_command(client, args)) elif command == "xdr-list-roles": return_results(list_roles_command(client, args)) elif command in ("xdr-set-user-role", "xdr-remove-user-role"): return_results(change_user_role_command(client, args)) elif command == "xdr-update-alert": # This command is Deprecated, use xdr-issue-update instead. return_results(update_alerts_in_xdr_command(client, args)) elif command == "xdr-bioc-list": return_results(bioc_list_command(client, args)) elif command == "xdr-bioc-create": return_results(bioc_create_command(client, args)) elif command == "xdr-bioc-update": return_results(bioc_update_command(client, args)) elif command == "xdr-bioc-delete": return_results(bioc_delete_command(client, args)) elif command == "xdr-correlation-rule-list": return_results(correlation_rule_list_command(client, args)) elif command == "xdr-correlation-rule-create": return_results(correlation_rule_create_command(client, args)) elif command == "xdr-correlation-rule-update": return_results(correlation_rule_update_command(client, args)) elif command == "xdr-correlation-rule-delete": return_results(correlation_rule_delete_command(client, args)) elif command == "xdr-api-key-list": return_results(api_key_list_command(client, args)) elif command == "xdr-api-key-delete": return_results(api_key_delete_command(client, args)) elif command == "xdr-vulnerability-details-get": return_results(get_vulnerability_details_command(client, args)) elif command == "xdr-healthcheck-run": return_results(healthcheck_run_command(client)) elif command == "xdr-endpoint-triage-preset-list": return_results(endpoint_triage_preset_list_command(client)) elif command == "xdr-endpoint-triage": return_results(endpoint_triage_command(client, args)) elif command == "xdr-automation-script-create": return_results(automation_script_create_command(client, args)) elif command == "xdr-automation-script-get": return_results(automation_script_get_command(client, args)) elif command == "xdr-automation-script-delete": return_results(automation_script_delete_command(client, args)) elif command == "xdr-automation-playbook-create": return_results(automation_playbook_create_command(client, args)) elif command == "xdr-automation-playbook-get": return_results(automation_playbook_get_command(client, args)) elif command == "xdr-automation-playbook-delete": return_results(automation_playbook_delete_command(client, args)) elif command == "xdr-case-list": return_results(case_list_command(client, args)) elif command == "xdr-case-update": return_results(case_update_command(client, args)) elif command == "xdr-case-artifact-list": return_results(case_artifact_list_command(client, args)) elif command == "xdr-issue-list": return_results(list_issues_command(client, args)) elif command == "xdr-issue-create": return_results(create_issue_command(client, args)) elif command == "xdr-issue-update": return_results(update_issue_command(client, args)) except Exception as err: return_error(str(err)) if __name__ in ("__main__", "__builtin__", "builtins"): main()