threatlookup Search Operator
The threatlookup operator identifies suspicious indicators of compromise in your data which match your threat intelligence sources. Using this operator provides security analytics to help you to detect threats in your environment.
This operator supersedes the more limited threatip search operator, allowing matches against multiple sources for multiple kinds of indicators.
Syntax
threatlookup [singleIndicator] [source="<source_value>"] <indicator>
Where:
-
singleIndicatorreturns the single best matching threat intelligence entry. (In the response,num_matchesindicates how many total matches across your sources there are.) IfsingleIndicatoris not specified, all matching entries from your intelligence sources are returned in separate rows.Note that
singleIndicatorreturns the most recent, highest confidence entry from your sources. If there's a tie, the winning entry is whichever the backend storage returned first. -
sourceis the threat intelligence source to search for the threat intelligence indicator. Ifsourceis not specified, all sources are searched. -
<indicator>is the field name containing an indicator to look up. At least one field name is required.
Response fields
Query responses return the following normalized indicator fields, which will all be null if no matching record is found:
actorsconfidencefieldsidimportedindicatorkill_chainnum_matches(ifsingleIndicatoris used)sourcethreat_typetypeupdatedvalid_fromvalid_until
Examples
_index=sec_record*
| threatlookup singleIndicator srcDevice_ip
| where _threatlookup.confidence > 50
| timeslice 1h
| count by _timeslice
_index=sec_record*
| threatlookup source="mysource" srcDevice_ip
| where _threatlookup.confidence > 50
| timeslice 1h
| count by _timeslice
Format timestamp results
Timestamps for the following response fields return results as an integer because they use Unix time (also known as epoch time):
_threatlookup.imported_threatlookup.valid_from_threatlookup.valid_until_threatlookup.updated
To convert the timestamp results to a readable output, you must format it in the search itself with formatDate. For example:
_index=sec_record*
| threatlookup source="mysource" device_ip
| formatDate(_threatlookup.valid_until, "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") as valid_until
Upcoming change
The behavior of the threatlookup operator is changing in an upcoming release. Previously, rows without matches in threat intelligence sources were excluded from search results. With the new behavior, threatlookup will return one result row for each input indicator, even if there is no threat intel match. In such cases, the normalized threatlookup fields (for example, _threatlookup.source, _threatlookup.confidence, etc.) will be null.
Impact
If you have saved queries, dashboards, or other workflows relying on the current behavior, they may return additional rows after this change. This could require you to update your logic to explicitly exclude rows with no matches.
How to adapt
To retain the previous filtering and exclude rows without threat intel matches, add an explicit non-match filtering check, for example:
_index=sec_record*
| threatlookup singleIndicator srcDevice_ip
| where _threatlookup.confidence > 50
| where !isNull(_threatlookup.source)
| timeslice 1h
| count by _timeslice
If you do not add this check, one row will be returned for every input, regardless of matches.
For example, given the log message:
198.51.100.7 - - [02/Dec/2025:08:40:01 +0000] "GET /admin/login.php HTTP/1.1" 404 250 "-" "Mozilla/5.0"
The previous query was:
* | parse regex "(?<client_ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})"
| threatlookup singleIndicator client_ip
Before, no result is returned if 198.51.100.7 is not in your threat intel sources.
After, one result row is returned, containing _threatlookup.* fields as null.