Cortex XSOAR Tips & Tricks – Leveraging dynamic sections – text

This entry is part 11 in the series Cortex XSOAR Tips & Tricks


Cortex XSOAR is a security oriented automation platform, and one of the areas where it stands out is customization.

A recurring problem in a SOC (Security Operation Center) is data availability. As a SOC Analyst, doing a thorough analysis of a security incident requires having access to many pieces of information in order to acquire context on the events you are investigating. In a less mature SOC, this information is at best scattered in many tools, and at worst hardly available. This can be overcome by using multiple data sources to ingest contextual information into your Security Automation and Automated Response platform (SOAR). In turn, this allows you to provide a single pane of glass to the analysts which can then focus on meaningful work, and eliminate data collection from their daily tasks.


In this blogpost, we will focus on the use of dynamic sections to customize layouts in Cortex XSOAR. We will show that they can be used to display raw incident data for debugging purposes without cluttering the main workplace of our analysts.

A dynamic section is a layout element which you can add to a layout tab for either an incident or an indicator.
The fundamental difference between it and most other available layout elements is that it is not bound to displaying incident fields or fields of indicators related to the current incident on display, but instead is purely automation based.
This means that upon being rendered, a dynamic section executes an automation, and it is both the specific format and output of that automation that dictates the style and content that will be rendered.

This is not unlike the behavior of field display scripts, but these will be covered in a later post.

Real World Example

As part of our operations as an MSSP (Managed Security Services Provider), we are often faced with alert ingestion issues or mishaps.

One way these occur is that an alert will be fetched into Cortex XSOAR but some of it’s important features will not have been picked up by our extraction logic. This could materialize as missing fields in indicators or missing indicators all together. We may for example have received an alert for suspicious actions taken by a user, yet that very user was not added to the incident as an indicator, nor were details about these actions.

Incident Info tab of a Cortex XSOAR incident – the name of the incident points to unsanctioned cloud app usage by a user, but neither information about the user nor about the unsanctioned app was extracted.

This could happen in many different ways, most commonly that the exact data scheme used by the tool that generated the alert has changed. When this happens, the information we want to extract is present in the alert we fetch, it’s just not located where we’re used to find it. In such cases, a manual inspection of the raw data that came in is sufficient to identify where the data we want can be found. However, as shown in the next screenshot, manually inspecting the raw data of an incident is not that user friendly in Cortex XSOAR.

View of the “Context Data” of an Cortex XSOAR incident – the presentation of the available data is unsuitable for manual inspection

To make it easier, we built our own dynamic section, which displays curated data from both the labels and some entries of an incident. The result is as follows:

In this example, Azure Active Directory identifiers are available and can be leveraged to get the details of the involved user. In a similar manner, the Cloud Application Id is available.

Our dynamic section is powered by an automation that enumerates the labels of the current incident.

ret_labels = {}
incident = demisto.incident()
if not (isinstance(incident, dict) and "labels" in incident.keys()):
labels = incident["labels"]
if not isinstance(labels, (list, List)):
for label in labels:

Similarly, it also enumerates specifically tagged war room entries.

ret_notes = {}
investigation_id = demisto.incident()["id"]
uri = f"investigation/{investigation_id}"
body = {
	"pageSize": 100,
	"categories": [],
	"tags": ["raw_data"],
	"notCategories": [],
	"usersAndOperator": False,
	"tagsAndOperator": False,
body = json.dumps(body, indent=4)
args = {"uri": uri, "body": body}
res_cmd = demisto.executeCommand("demisto-api-post", args)
for res in res_cmd:
	if not (isinstance(res, dict) and isinstance(contents := res.get("Contents"), dict)):
	if not isinstance(response := contents.get("response"), dict):
	if not isinstance(entries := response.get("entries"), (list, List)):
	for entry in entries:

Once the incident labels are fetched, we extract their contents:

for label in labels:
	if not isinstance(label, dict):
	label_type, label_value = label.get("type"), label.get("value")
	if not (isinstance(label_type, str) and isinstance(label_value, str)):
		label_value = json.loads(label_value)
	except Exception:
		ret_labels.update({label_type: label_value})
	except Exception:

In a similar fashion, for each returned War Room entry, we extract the name of the parent playbook task and the content of the entry:

for entry in entries:
	key = ""
	if not isinstance(entry, dict):
	if isinstance(entry_id := entry.get("id"), str):
		key += entry_id
	if isinstance(entry_task := entry.get("entryTask"), dict):
		if isinstance(task_name := entry_task.get("taskName"), str):
			key += " - " + task_name
	value = None
	if isinstance(cnt := entry.get("contents"), str):
			value = json.loads(cnt)
		except Exception:
			value = cnt
	ret_notes.update({key: value})

To tie it all up, and because our goal is to offer a tree like navigable output, we structure our outputted data into a dictionary.

ret = {
	"notes": ret_notes,
	"labels": ret_labels

At that point, we cannot just output this dictionary as is, we need to encapsulate it in a way that will indicate to the layout that we want this layout element to be shown as a JSON tree.

results = CommandResults(raw_response = ret)

By now, our code is good to go and all we need to do is to edit our incident layout to add a new tab and create a new dynamic section powered by the automation we just built.

In Cortex XSOAR, navigate to Settings, Objects setup, Layouts, and either modify an existing layout or create your own. From there you can add a new General Purpose Dynamic Section.

Once your General Purpose Dynamic Section is added to your layout tab, you can edit it and choose the automation it executes. If your automation does not show up in the list of available ones, make sure you added the “dynamic-section” tag to it.

In this blog post, we have shown you how to display complex data in an incident layout which can be used by a security analyst to provide more context. In future posts, we will present more detailed context additions that tie in nicely with the Cortex XSOAR user interface.


Palo Alto Cortex XSOAR documentation: how to add a custom widget to the incident and indicator pages

Microsoft Sentinel Cloud Application Entity Identifiers

About the author

Benjamin Danjoux

Benjamin is a senior engineer in NVISO’s SOAR engineering team.As the SOAR engineering design lead, he is responsible for the overall architecture and organization of the automated workflows running on Palo Alto Cortex XSOAR, which enables the NVISO SOC analysts to detect attackers in customer environments.

Series Navigation<< Cortex XSOAR Tips & Tricks – Creating indicator relationships in integrationsCortex XSOAR Tips & Tricks – Dealing with dates >>

One thought on “Cortex XSOAR Tips & Tricks – Leveraging dynamic sections – text

Leave a Reply