Formatting scripts validate input and modify how indicators display.
A formatting script has the following main functions:
Validating the input (for example, checking that the Top Level Domain (TLD) is valid).
Modifying how the indicator appears in Cortex XSOAR such as the War Room, Reports, etc.
After indicators are extracted according to the defined regex, the defined regex finds the indicator value and the formatting script modifies the string value, so it can be used in Cortex XSOAR. For example the IP indicator uses the UnEscapeIPs
formatting script, which removes any defanged characters from an IP address, such as 127[.]0[.]0[.]1
to 127.0.0.1
. In the War Room, you can click on the IP address to view the extracted IP address. This extracted indicator using the formatting script is added to the Threat Intel database.
To apply a formatting script to an indicator type:
Go to
→ → → .Select the indicator type, click Edit.
Select the desired formatting script.
Formatting scripts must have the
indicator-format
tag to appear in the list.
Note
Formatting scripts for out-of-the-box indicator types are system level, which means that the formatting scripts for these indicator types are not configurable. To create a formatting script for an out-of-the-box indicator type, you need to disable the existing indicator type and create a new (custom) indicator type. If you configured a formatting script before this change and updated your content, this configuration reverts to content settings (empty).
Out-of-the-Box Formatting Script Examples
In the
page, there are a number of out-of-the box formatting scripts, including:UnEscapeIPs
ExtractDomainAndFQDNFromUrlAndEmail
This script is used by the Domain indicator, extracts domains and FQDN from URLs and emails. It removes prefixes such as proofpoint or safelinks, removes escaped URLs, and extracts the FQDN, etc.
ExtractEmailV2
CLI Execution Examples
!UnEscapeIPs input=127.0.0[.]1
!UnEscapeIPs input=127.0.0[.]1,8.8.8[.]8
!UnEscapeIPs input=${contextdata.indicators}
(where the keycontextdata.indicators
in the context object, is an array)
Formatting Script Input
The formatting script requires a single input argument named input
that accepts a single indicator value or an array of indicator values. The input argument should be an array to accept multiple inputs and return an entry-result per input.
Argument | Description |
---|---|
| Accepts a string or array of strings representing the indicator value(s) to be formatted. Will be accessed within the script using In the script settings, the Is Array checkbox must be checked (see screenshot below).The script code must be able to handle a single indicator value (as string), multiple indicator values in CSV format (as string) and an array of single indicator values (array). |
Formatting Script Outputs
The indicators appear as a human readable format in Cortex XSOAR. The output should be an array of formatted indicators or an array of entry results (an entry result per indicator to be created). The entry result per input can be a JSON array to create multiple indicators. If the entry result is an empty string, it is ignored and no indicator is created.
Output Code Examples
Single-value result:
demisto.results([{ "Type": entryTypes["note"], "ContentsFormat": formats["json"], "Contents": [format(indicator)], "EntryContext": {"Domain": format(indicator)} }])
Multiple-value results:
entries_list = [] for indicator in argToList(demisto.args().get('input', ‘’)): input_entry = { "Type": entryTypes["note"], "ContentsFormat": formats["json"], "Contents": [format(indicator)], "EntryContext": {"Domain": format(indicator)} } if input_entry.get("Contents") == [""]: input_entry['Contents'] = [] entries_list.append(input_entry) if entries_list: demisto.results(entries_list) else: # Return empty string so it wouldn't create an empty indicator. demisto.results('')
For more information about code conventions, see https://xsoar.pan.dev/docs/integrations/code-conventions#return_results.
Complete Formatting Script Example
In the following example, a prefix will be removed from the indicators.
def formatIndicator(indicator): return indicator.removeprefix('/') # argToList returns the argument as is if it's already a list so no need to check here the_input = argToList(demisto.args().get('input')) entries_list = [] # Otherwise assumes it's already an array for item in the_input: input_entry = { "Type": entryTypes["note"], "ContentsFormat": formats["json"], "Contents": [formatIndicator(item)], "EntryContext": {"Domain": item} } if input_entry.get("Contents") == ['']: input_entry['Contents'] = [] entries_list.append(input_entry) if entries_list: demisto.results(entries_list) else: # Return empty string so it wouldn't create an empty domain indicator. demisto.results('')