RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/Cline rules/repulsivityy/elevate_2025

Cline rules

.clinerules/YARAL_SYNTAX.md
Cline rules

Quality

45/100

Scores the file, not the repository.

Length

20,652 words

600 headings · 342 code blocks

Repository

2

— · pushed 178 days ago

Last changed

3 days ago

First indexed 3 days ago.
repulsivityy/elevate_2025/.clinerules/YARAL_SYNTAX.mdRawGitHub
1 
2# YARA-L 2.0 language syntax
3 
4Supported in:
5 
6Google secops
7[Siem](/chronicle/docs/secops/google-secops-siem-toc)
8 
9This section describes the major elements of the YARA-L syntax. See also [Overview of the YARA-L 2.0 language](/chronicle/docs/detection/yara-l-2-0-overview).
10 
11**Note:** YARA-L syntax doesn't allow negative integers. For example,
12`$e.principal.ip[-1]` is not valid. Replace `-1` with `0-1`.
13 
14## Rule structure
15 
16For YARA-L 2.0, you must specify variable declarations, definitions, and usages in the following order:
17 
181. meta
192. events
203. match (optional)
214. outcome (optional)
225. condition
236. options (optional)
24 
25**Note:** If you exclude `match`, the rule can match against a single event.
26 
27The following example illustrates the generic structure of a rule:
28 
29```
30rule <rule Name>
31{
32 meta:
33 // Stores arbitrary key-value pairs of rule details, such as who wrote
34 // it, what it detects on, version control, etc.
35 
36 events:
37 // Conditions to filter events and the relationship between events.
38 
39 match:
40 // Values to return when matches are found.
41 
42 outcome:
43 // Additional information extracted from each detection.
44 
45 condition:
46 // Condition to check events and the variables used to find matches.
47 
48 options:
49 // Options to turn on or off while executing this rule.
50}
51 
52```
53 
54## Meta section syntax
55 
56Meta section is composed of multiple lines, where each line defines a key-value pair. A key part must be an unquoted string, and a value part must be a quoted string:
57 
58`<key> = "<value>"`
59 
60The following is an example of a valid `meta` section line:
61 
62```
63meta:
64 author = "Google"
65 severity = "HIGH"
66 
67```
68 
69## Events section syntax
70 
71In the `events` section, list the predicates to specify the following:
72 
73* Variable declarations
74* Event variable filters
75* Event variable joins
76 
77### Variable declarations
78 
79For variable declarations, use the following syntax:
80 
81* `<EVENT_FIELD> = <VAR>`
82* `<VAR> = <EVENT_FIELD>`
83 
84Both are equivalent, as shown in the following examples:
85 
86* `$e.source.hostname = $hostname`
87* `$userid = $e.principal.user.userid`
88 
89This declaration indicates that this variable represents the specified field for the event variable. When the event field is a repeated field, the match variable can represent any value in the array. It is also possible to assign multiple event fields to a single match or placeholder variable. This is a transitive join condition.
90 
91For example, the following:
92 
93* `$e1.source.ip = $ip`
94* `$e2.target.ip = $ip`
95 
96Are equivalent to:
97 
98* `$e1.source.ip = $ip`
99* `$e1.source.ip = $e2.target.ip`
100 
101When a variable is used, the variable must be declared through variable declaration. If a variable is used without any declaration, it is regarded as a compilation error.
102 
103### Event variable filters
104 
105A [boolean expression](#boolean_expressions) that acts on a single event variable is considered a filter.
106 
107### Event variable joins
108 
109All event variables used in the rule must be joined with every other event variable in either of the following ways:
110 
111* Directly through an equality comparison between event fields of the two joined event variables, for example: `$e1.field = $e2.field`. The expression must not include arithmetic.
112* Indirectly through a transitive join involving only an event field (see [variable declaration](#variable_declarations) for a definition of "transitive join"). The expression must not include arithmetic.
113 
114For example, assuming $e1, $e2, and $e3 are used in the rule, the following `events` sections are valid.
115 
116```
117events:
118 $e1.principal.hostname = $e2.src.hostname // $e1 joins with $e2
119 $e2.principal.ip = $e3.src.ip // $e2 joins with $e3
120 
121```
122 
123```
124events:
125 // $e1 joins with $e2 via function to event comparison
126 re.capture($e1.src.hostname, ".*") = $e2.target.hostname
127 
128```
129 
130```
131events:
132 // $e1 joins with $e2 via an `or` expression
133 $e1.principal.hostname = $e2.src.hostname
134 or $e1.principal.hostname = $e2.target.hostname
135 or $e1.principal.hostname = $e2.principal.hostname
136 
137```
138 
139```
140events:
141 // all of $e1, $e2 and $e3 are transitively joined via the placeholder variable $ip
142 $e1.src.ip = $ip
143 $e2.target.ip = $ip
144 $e3.about.ip = $ip
145 
146```
147 
148```
149events:
150 // $e1 and $e2 are transitively joined via function to event comparison
151 re.capture($e2.principal.application, ".*") = $app
152 $e1.principal.hostname = $app
153 
154```
155 
156**Note:** If your sole join condition is an `or` chain, a function to event
157comparison, or a combination of both, then the rule may perform poorly.
158 
159However, here are examples of invalid `events` sections.
160 
161```
162events:
163 // Event to arithmetic comparison is an invalid join condition for $e1 and $e2.
164 $e1.principal.port = $e2.src.port + 1
165 
166```
167 
168```
169events:
170 $e1.src.ip = $ip
171 $e2.target.ip = $ip
172 $e3.about.ip = "192.1.2.0" //$e3 is not joined with $e1 or $e2.
173 
174```
175 
176```
177events:
178 $e1.src.port = $port
179 
180 // Arithmetic to placeholder comparison is an invalid transitive join condition.
181 $e2.principal.port + 800 = $port
182 
183```
184 
185## Match section syntax
186 
187In the `match` section, list the match variables for group events before checking for match conditions. Those fields are returned with each match.
188 
189* Specify what each match variable represents in the `events` section.
190* Specify the time duration to use to correlate events after the `over` keyword. Events outside the time duration are ignored.
191* Use the following syntax to specify the time duration: `<number><m/h/d>`
192 
193 Where `m/h/d` means minutes, hours, and days respectively.
194* Minimum time you can specify is 1 minute.
195* Maximum time you can specify is 48 hours.
196 
197The following is an example of a valid `match`:
198 
199```
200$var1, $var2 over 5m
201 
202```
203 
204This statement returns `$var1` and `$var2` (defined in the `events` section) when the rule finds a match. The time specified is 5 minutes. Events that are more than 5 minutes apart are not correlated and therefore ignored by the rule.
205 
206Here is another example of a valid `match` section:
207 
208```
209$user over 1h
210 
211```
212 
213This statement returns `$user` when the rule finds a match. The time window specified is 1 hour. Events that are more than an hour apart are not correlated. The rule does not consider them to be a detection.
214 
215Here is another example of a valid `match` section:
216 
217```
218$source_ip, $target_ip, $hostname over 2m
219 
220```
221 
222This statement returns `$source_ip`, `$target_ip`, and `$hostname` when the rule finds a match. The time window specified is 2 minutes. Events that are more than 2 minutes apart are not correlated. The rule does not consider them to be a detection.
223 
224The following examples illustrate **invalid** `match` sections:
225 
226* `var1, var2 over 5m // invalid variable name`
227* `$user 1h // missing keyword`
228 
229### Zero value handling in the match section
230 
231Rules Engine implicitly filters out the zero values for all placeholders that
232are used in the match section (`""` for
233string, `0` for numbers, `false` for booleans, the value in position 0
234for [enumerated types](/chronicle/docs/reference/udm-field-list#event_enumerated_types)).
235The following example illustrates rules that filter out the zero values.
236 
237```
238rule ZeroValuePlaceholderExample {
239 meta:
240 events:
241 // Because $host is used in the match section, the rule behaves
242 // as if the following predicate was added to the events section:
243 // $host != ""
244 $host = $e.principal.hostname
245 
246 // Because $otherPlaceholder was not used in the match section,
247 // there is no implicit filtering of zero values for $otherPlaceholder.
248 $otherPlaceholder = $e.principal.ip
249 
250 match:
251 $host over 5m
252 
253 condition:
254 $e
255}
256 
257```
258 
259However, if a placeholder is assigned to a function, rules don't
260implicitly filter out the zero values of placeholders that are used in
261the match section.
262The following example illustrates rules that filter out the zero values:
263 
264```
265rule ZeroValueFunctionPlaceholder {
266 meta:
267 events:
268 // Even though $ph is used in the match section, there is no
269 // implicit filtering of zero values for $ph, because $ph is assigned to a function.
270 $ph = re.capture($e.principal.hostname, "some-regex")
271 
272 match:
273 $ph over 5m
274 
275 condition:
276 $e
277}
278 
279```
280 
281To disable the implicit filtering of zero values,
282you can use the `allow_zero_values` option in the [options section](#options_section_syntax).
283 
284### Hop window
285 
286By default, YARA-L 2.0 rules with a match section are evaluated using hop windows.
287The time range of the rule's execution is divided into a set of overlapping hop windows,
288each with the duration specified in the `match` section. Events are then correlated
289within each hop window.
290 
291For example, for a rule that is run over the time range [1:00, 2:00], with a
292`match` section over `30m`, a possible set of overlapping hop windows
293that could be generated is [1:00, 1:30], [1:03, 1:33] and [1:06, 1:36].
294These windows are used to correlate multiple events.
295 
296### Sliding window
297 
298Using hop windows is not an effective way to search for events that happen in a specific order (for example, `e1` happens up to 2
299minutes after `e2`). An occurrence of event `e1` and an occurrence of event `e2`
300are correlated only if they fall into the same hop window generated.
301 
302A more effective way to search for such event sequences is to use sliding windows.
303Sliding windows with the duration specified in the `match` section are generated when
304beginning or ending with a specified pivot event variable. Events are then
305correlated within each sliding window. This makes it possible to search for
306events that happen in a specific order (for example, `e1` happens within 2
307minutes of `e2`). An occurrence of event `e1` and an occurrence of event `e2`
308are correlated if event `e1` occurs within the sliding window duration after
309event `e2`.
310 
311Specify sliding windows in the `match` section of a rule as follows:
312 
313`<match-var-1>, <match-var-2>, ... over <duration> before|after <pivot-event-var>`
314 
315The pivot event variable is the event variable that sliding windows are based
316on. If you use the `before` keyword, sliding windows are generated, ending with
317each occurrence of the pivot event. If the `after` keyword is used, sliding
318windows are generated beginning with each occurrence of the pivot event.
319 
320The following are examples of valid sliding window usages:
321 
322* `$var1, $var2 over 5m after $e1`
323* `$user over 1h before $e2`
324 
325See [a sliding window rule example](/chronicle/docs/detection/yara-l-2-0-overview#sliding_window_rule_example).
326 
327**Note:** Using sliding windows instead of hop windows has been known to result in
328slower performance. We recommend using sliding windows only for
329specific cases, such as when event order is absolutely necessary or when
330searching for the non-existence of events.
331 
332We recommend not using sliding windows for single-event rules, because
333sliding windows are designed to detect multiple events. If one of
334your rules falls in this category, We recommend one of
335the following workarounds:
336 
337* Convert the rule to use multiple event variables, and update the condition
338 section if the rule requires more than one occurrence of the event.
339 + Optionally, consider adding timestamp filters instead of using a sliding window.
340 For example, `$permission_change.metadata.event_timestamp.seconds < $file_creation.metadata.event_timestamp.seconds`
341* Remove the sliding window.
342 
343## Outcome section syntax
344 
345In the `outcome` section, you can define up to 20 outcome variables, with
346arbitrary names. These outcomes will be stored in the detections generated by
347the rule. Each detection may have different values for the outcomes.
348 
349The outcome name, `$risk_score`, is special. You can optionally define an
350outcome with this name, and if you do, it must be an integer or float type. If populated,
351the `risk_score` will be shown in the
352[Enterprise Insights view](https://cloud.google.com/chronicle/docs/investigation/view-alerts-insights.md) for
353alerts that come from rule detections.
354 
355If you don't include a `$risk_score` variable in the outcome section of a rule,
356one of the following default values is set:
357 
358* If the rule is configured to generate an alert, then `$risk_score` is set to 40.
359* If the rule is not configured to generate an alert, then `$risk_score` is set to 15.
360 
361The value of `$risk_score` is stored in the `security_result.risk_score` UDM field.
362 
363### Outcome variable data types
364 
365Each outcome variable can have a different data type, which is determined by the expression
366used to compute it. We support the following outcome data types:
367 
368* integer
369* floats
370* string
371* lists of integers
372* lists of floats
373* lists of strings
374 
375### Conditional logic
376 
377You can use conditional logic to compute the value of an outcome. Conditionals
378are specified using the following syntax pattern:
379 
380```
381if(BOOL_CLAUSE, THEN_CLAUSE)
382if(BOOL_CLAUSE, THEN_CLAUSE, ELSE_CLAUSE)
383 
384```
385 
386You can read a conditional expression as "if BOOL\_CLAUSE is true, then return
387THEN\_CLAUSE, else return ELSE\_CLAUSE".
388 
389BOOL\_CLAUSE must evaluate to a boolean value. A BOOL\_CLAUSE expression takes a
390similar form as expressions in the `events` section. For example, it can
391contain:
392 
393* UDM field names with comparison operator, for example:
394 
395 `if($context.graph.entity.user.title = "Vendor", 100, 0)`
396* placeholder variable that was defined in the `events` section, for example:
397 
398 `if($severity = "HIGH", 100, 0)`
399* another outcome variable defined in the `outcome` section, for example:
400 
401 `if($risk_score > 20, "HIGH", "LOW")`
402* functions that return a boolean, for example:
403 
404 `if(re.regex($e.network.email.from, `.*altostrat.com`), 100, 0)`
405* look up in a [reference list](#reference_lists_syntax), for example:
406 
407 `if($u.principal.hostname in %my_reference_list_name, 100, 0)`
408* aggregation comparison, for example:
409 
410 `if(count($login.metadata.event_timestamp.seconds) > 5, 100, 0)`
411 
412The THEN\_CLAUSE and ELSE\_CLAUSE must be the same data type. We support integers, floats, and strings.
413 
414You can omit the ELSE\_CLAUSE if the data type is integer or a float. If omitted, the
415ELSE\_CLAUSE evaluates to 0. For example:
416 
417```
418`if($e.field = "a", 5)` is equivalent to `if($e.field = "a", 5, 0)`
419 
420```
421 
422You must provide the ELSE\_CLAUSE if the data type is string or if the THEN\_CLAUSE
423is a placeholder variable or outcome variable.
424 
425### Mathematical operations
426 
427You can use mathematical operations to compute integer or float data type in the `outcome`and `events` sections of a rule. Google Security Operations supports addition, subtraction, multiplication, division, and modulus as top level operators in a computation.
428 
429The following snippet is an example computation in the `outcome` section:
430 
431```
432outcome:
433 $risk_score = max(100 + if($severity = "HIGH", 10, 5) - if($severity = "LOW", 20, 0))
434 
435```
436 
437Mathematical operations are allowed on the following types of operands as long as
438each operand and the entire arithmetic expression is properly aggregated (See [Aggregations](#aggregations)):
439 
440* Numeric event fields
441* Numeric placeholder variables defined in the `events` section
442* Numeric outcome variables defined in the `outcome` section
443* Functions returning ints or floats
444* Aggregations returning ints or floats
445 
446Modulus is not allowed on floats.
447 
448### Placeholder variables in outcomes
449 
450When computing outcome variables, you can use placeholder variables which were
451defined in the events section of your rule. In this example, assume that
452`$email_sent_bytes` was defined in the events section of the rule:
453 
454Single-event example:
455 
456```
457// No match section, so this is a single-event rule.
458 
459outcome:
460 // Use placeholder directly as an outcome value.
461 $my_outcome = $email_sent_bytes
462 
463 // Use placeholder in a conditional.
464 $other_outcome = if($file_size > 1024, "SEVERE", "MODERATE")
465 
466condition:
467 $e
468 
469```
470 
471Multi-event example:
472 
473```
474match:
475 // This is a multi event rule with a match section.
476 $hostname over 5m
477 
478outcome:
479 // Use placeholder directly in an aggregation function.
480 $max_email_size = max($email_sent_bytes)
481 
482 // Use placeholder in a mathematical computation.
483 $total_bytes_exfiltrated = sum(
484 1024
485 + $email_sent_bytes
486 + $file_event.principal.file.size
487 )
488 
489condition:
490 $email_event and $file_event
491 
492```
493 
494### Outcome variables in outcome assignment expressions
495 
496Outcome variables can be used to derive other outcome variables, similar to
497placeholder variables defined in the `events` section. You can refer to an outcome
498variable in the assignment of another outcome variable with a `$` token followed
499by the variable name. Outcome variables must be defined before they can be referenced
500in the rule text. When used in an assignment expression, outcome variables must
501not be aggregated (See [Aggregations](#aggregations)).
502 
503In the following example, the outcome variable `$risk_score` derives its
504value from the outcome variable `$event_count`:
505 
506Multi-event example:
507 
508```
509match:
510 // This is a multi event rule with a match section.
511 $hostname over 5m
512 
513outcome:
514 // Aggregates all timestamp on login events in the 5 minute match window.
515 $event_count = count($login.metadata.event_timestamp.seconds)
516 
517 // $event_count cannot be aggregated again.
518 $risk_score = if($event_count > 5, "SEVERE", "MODERATE")
519 
520 // This is the equivalent of the 2 outcomes above combined.
521 $risk_score2 = if(count($login.metadata.event_timestamp.seconds) > 5, "SEVERE", "MODERATE")
522 
523condition:
524 $e
525 
526```
527 
528Outcome variables can be used in any type of expression on the right-hand-side of an outcome assignment,
529except in the following expressions:
530 
531* Aggregations
532* `Arrays.length()` function calls
533* With `any` or `all` modifiers
534 
535### Aggregations
536 
537Repeated event fields are non-scalar values. That is, a single variable points to
538multiple values. For example, the event field variable `$e.target.ip` is a repeated field
539and can have zero, one, or many ip values. It is a non-scalar value. Whereas the event field variable
540`$e.principal.hostname` is not a repeated field and only has 1 value (i.e. a scalar value).
541 
542Similarly, both non-repeated event fields and repeated event fields used in the outcome section
543of a rule with a match window are non-scalar values. For example, the following rule groups events
544using a match section and refers to a non-repeated event field in the outcome section:
545 
546```
547rule OutcomeAndMatchWindow{
548 ...
549 match:
550 $userid over 5m
551 outcome:
552 $hostnames = array($e.principal.hostname)
553 ...
554}
555 
556```
557 
558Any 5-minute window the rule executes over might contain zero, one, or many events. The outcome section
559operates on all events in a match window. Any event field variable referred to within the
560outcome section can point to zero, one, or many values of the field on each event in the match window.
561For example, if a 5-minute window contains 5 `$e` events, `$e.principal.hostname`
562in the outcome section points to five different hostnames. The event field variable
563`$e.principal.hostname` is treated as a non-scalar value in the `outcome` section of this rule.
564 
565Because outcome variables must always yield a single scalar value, any non-scalar value which
566an outcome assignment depends on must be aggregated to yield a single scalar value.
567In an outcome section, the following are non-scalar values and must be aggregated:
568 
569* Event fields (repeated or non-repeated) when the rule uses a match section
570* Event placeholders (repeated or non-repeated) when the rule uses a match section
571* Repeated event fields when the rule does not use a match section
572* Repeated event placeholders when the rule does not use a match section
573 
574Scalar event fields, scalar event placeholders, and constants can be wrapped in
575aggregation functions in rules that don't include a match section. However, in
576most cases, these aggregations return the wrapped value, making them unnecessary.
577An exception is the `array()` aggregation, which you can use to explicitly convert
578a scalar value into an array.
579 
580Outcome variables are treated like aggregations: they must not be re-aggregated
581when referred to in another outcome assignment.
582 
583You can use the following aggregation functions:
584 
585* `max()`: outputs the maximum over all possible values. Only works with integer and float.
586* `min()`: outputs the minimum over all possible values. Only works with integer and float.
587* `sum()`: outputs the sum over all possible values. Only works with integer and float.
588* `count_distinct()`: collects all possible values, then outputs the distinct count of
589 possible values.
590* `count()`: behaves like `count_distinct()`, but returns a non-distinct count of
591 possible values.
592* `array_distinct()`: collects all possible distinct values, then outputs a list of these values. It
593 will truncate the list of distinct values to 25 random elements. The deduplication
594 to get a distinct list is applied first, then the truncation is applied.
595* `array()`: behaves like `array_distinct()`, but returns a non-distinct list of
596 values. It also truncates the list of values to 25 random elements.
597* `period_start_for_max()`: start of the time period where the maximum of
598 the listed value occurred.
599* `period_start_for_min()`: start of the time period where the minimum of
600 the listed value occurred.
601 
602The aggregate function is important when a rule includes a `condition` section
603that specifies multiple events must exist, because the aggregate function will
604operate on all the events that generated the detection.
605 
606For example, if your `outcome` and `condition` sections contain:
607 
608```
609outcome:
610 $asset_id_count = count($event.principal.asset_id)
611 $asset_id_distinct_count = count_distinct($event.principal.asset_id)
612 
613 $asset_id_list = array($event.principal.asset_id)
614 $asset_id_distinct_list = array_distinct($event.principal.asset_id)
615 
616condition:
617 #event > 1
618 
619```
620 
621Since the condition section requires there to be more than one `event` for each
622detection, the aggregate functions will operate on multiple events. Suppose the
623following events generated one detection:
624 
625```
626event:
627 // UDM event 1
628 asset_id="asset-a"
629 
630event:
631 // UDM event 2
632 asset_id="asset-b"
633 
634event:
635 // UDM event 3
636 asset_id="asset-b"
637 
638```
639 
640Then the values of your outcomes will be:
641 
642* $asset\_id\_count = `3`
643* $asset\_id\_distinct\_count = `2`
644* $asset\_id\_list = `["asset-a", "asset-b", "asset-b"]`
645* $asset\_id\_distinct\_list = `["asset-a", "asset-b"]`
646 
647#### Things to know when using the outcome section:
648 
649Other notes and restrictions:
650 
651* The `outcome` section cannot reference a new placeholder variable which
652 wasn't already defined in the `events` section or in the `outcome` section.
653* The `outcome` section cannot use event variables that have not
654 been defined in the `events` section.
655* The `outcome` section can use an event field that was not
656 used in the `events` section, given that the event variable that the event
657 field belongs to was already defined in the `events` section.
658* The `outcome` section can only correlate event variables that have already
659 been correlated in the `events` section. Correlations happen when two
660 event fields from different event variables are equated.
661 
662You can find an example using the outcome section in
663[Overview of the YARA-L 2.0](/chronicle/docs/detection/yara-l-2-0-overview#rule_with_outcome_section_example).
664See [Create context-aware analytics](/chronicle/docs/detection/context-aware-analytics#outcome_section) for details on detection
665deduping with the outcome section.
666 
667## Condition section syntax
668 
669* specify a match condition over events and placeholders defined in the `events` section. See the following section, *Event and placeholder conditionals*, for more details.
670* (optional) use the `and` keyword to specify a match condition using outcome variables defined in the `outcome` section. See the following section, *Outcome conditionals*, for more details.
671 
672### Count character
673 
674The `#` character is a special character in the `condition` section. If it is
675used before any event or placeholder variable name, it represents the number of
676distinct events or values that satisfy all of the `events` section conditions.
677 
678For example, `#c > 1` means the variable `c` must occur more than 1 time.
679 
680### Value character
681 
682The `$` character is a special character in the `condition` section. If it is
683used before any outcome variable name, it represents the value of that outcome.
684 
685If it is used before any event or placeholder variable name (for example,
686`$event`), it represents `#event > 0`.
687 
688### Event and placeholder conditionals
689 
690List condition predicates for events and placeholder variables here, joined
691with the keyword `and` or `or`. The keyword `and` can be used between any
692conditions, but the keyword `or` can only be used when the rule only has a
693single event variable.
694 
695A valid example of using `or` between two placeholders on the same event:
696 
697```
698rule ValidConditionOr {
699 meta:
700 events:
701 $e.metadata.event_type = "NETWORK_CONNECTION"
702 
703 // Note that all placeholders use the same event variable.
704 $ph = $e.principal.user.userid // Define a placeholder variable to put in match section.
705 $ph2 = $e.principal.ip // Define a second placeholder variable to put in condition section.
706 $ph3 = $e.principal.hostname // Define a third placeholder variable to put in condition section.
707 
708 match:
709 $ph over 5m
710 
711 condition:
712 $ph2 or $ph3
713}
714 
715```
716 
717An invalid example of using `or` between two conditions on different events:
718 
719```
720rule InvalidConditionOr {
721 meta:
722 events:
723 $e.metadata.event_type = "NETWORK_CONNECTION"
724 $e2.graph.metadata.entity_type = "FILE"
725 $e2.graph.entity.hostname = $e.principal.hostname
726 
727 $ph = $e.principal.user.userid // Define a placeholder variable to put in match section.
728 
729 match:
730 $ph over 5m
731 
732 condition:
733 $e or $e2 // This line will cause an error because there is an or between events.
734}
735 
736```
737 
738**Note:** Don't use the keyword `not` in event and placeholder conditionals.
739 
740### Bounded and Unbounded conditions
741 
742The following conditions are bounded conditions. They force the associated
743event variable to exist, meaning that at least one occurrence of the event must
744appear in any detection.
745 
746* `$var // equivalent to #var > 0`
747* `#var > n // where n >= 0`
748* `#var >= m // where m > 0`
749 
750The following conditions are unbounded conditions. They allow the associated
751event variable to not exist, meaning that it is possible that no occurrence of
752the event appears in a detection and any reference to fields on the event
753variable will yield a zero value. Unbounded conditions can be used to detect
754the absence of an event over a period of time. For example, a threat event
755without a mitigation event within a 10 minute window. Rules using unbounded
756conditions are called non-existence rules.
757 
758* `!$var // equivalent to #var = 0`
759* `#var >= 0`
760* `#var < n // where n > 0`
761* `#var <= m // where m >= 0`
762 
763**Note:** For non-existence rules, the detection engine adds a 1 hour delay to the
764expected latency (based on the rule's run frequency) to allow for late-arriving
765data.
766 
767#### Requirements for non-existence
768 
769For a rule with non-existence to compile, it must satisfy the following requirements:
770 
7711. At least one UDM event must have a bounded condition (that is, at least one UDM event must exist).
7722. If a placeholder has an unbounded condition, it must be associated with
773 at least one bounded UDM event.
7743. If an entity has an unbounded condition, it must be associated with at
775 least one bounded UDM event.
776 
777Consider the following rule with the condition section omitted:
778 
779```
780rule NonexistenceExample {
781 meta:
782 events:
783 $u1.metadata.event_type = "NETWORK_CONNECTION" // $u1 is a UDM event.
784 $u2.metadata.event_type = "NETWORK_CONNECTION" // $u2 is a UDM event.
785 $e1.graph.metadata.entity_type = "FILE" // $e1 is an Entity.
786 $e2.graph.metadata.entity_type = "FILE" // $e2 is an Entity.
787 
788 $user = $u1.principal.user.userid // Match variable is required for Multi-Event Rule.
789 
790 // Placeholder Associations:
791 // u1 u2
792 // | \ /
793 // port ip
794 // | \
795 // e1 e2
796 $u1.target.port = $port
797 $e1.graph.entity.port = $port
798 $u1.principal.ip = $ip
799 $u2.target.ip = $ip
800 $e2.graph.entity.ip = $ip
801 
802 // UDM-Entity Associations:
803 // u1 - u2
804 // | \ |
805 // e1 e2
806 $u1.metadata.event_type = $u2.metadata.event_type
807 $e1.graph.entity.hostname = $u1.principal.hostname
808 $e2.graph.entity.hostname = $u1.target.hostname
809 $e2.graph.entity.hostname = $u2.principal.hostname
810 
811 match:
812 $user over 5m
813 
814 condition:
815 <condition_section>
816}
817 
818```
819 
820The following are *valid* examples for the `<condition_section>`:
821 
822* `$u1 and !$u2 and $e1 and $e2`
823 + All UDM events and entities are present in the condition section.
824 + At least one UDM event is bounded.
825* `$u1 and !$u2 and $e1 and !$e2`
826 + `$e2`is unbounded, which is allowed because it is associated with `$u1`, which is bounded. If `$e2` was not associated with `$u1`, this would be invalid.
827* `#port > 50 and #ip = 0`
828 + No UDM events and entities are present in the condition section; however, the placeholders that are present cover all the UDM events and entities.
829 + `$ip` is assigned to both `$u1` and `$u2` and `#ip = 0` is an unbounded condition. However, bounded conditions are *stronger* than unbounded conditions. Since `$port` is assigned to `$u1` and `#port > 50` is a bounded condition, `$u1` is still bounded.
830 
831The following are *invalid* examples for the `<condition_section>`:
832 
833* `$u1 and $e1`
834 + Every UDM event and entity appearing in the Events Section must appear in
835 the Condition Section (or have a placeholder assigned to it that appears in the Condition Section).
836* `$u1, $u2, $e1, $u2, #port > 50`
837 + Commas are not allowed as condition separators.
838* `!$u1 and !$u2 and $e1 and $e2`
839 + Violates the first requirement that at least one UDM event is bounded.
840* `($u1 or #port < 50) and $u2 and $e1 and $e2`
841 + `or` keyword is not supported with unbounded conditions.
842* `($u1 or $u2) and $e1 and $e2`
843 + `or` keyword is not supported between different event variables.
844* `not $u1 and $u2 and $e1 and $e2`
845 + `not` keyword is not allowed for event and placeholder conditions.
846* `#port < 50 and #ip = 0`
847 + The placeholders that are present cover all the UDM events and entities; however, all of the conditions are unbounded. This means none of the UDM events are bounded, causing the rule to fail to compile.
848 
849**Note:** Don't use a `match` variable in the `condition` section. It is a semantic
850error since events are grouped by the `match` variable value.**Note:** Don't specify only **unbounded conditions** on all `event` variables that a `match` variable is assigned to. It is a semantic error. For a `match` variable value to be returned, at least one event must exist that contains the value.**Note:** In case of using a sliding window, the pivot event variable must be involved in at least one bounded condition.
851 
852### Outcome conditionals
853 
854List condition predicates for outcome variables here, joined with the keyword `and` or `or`, or preceded by the keyword `not`.
855 
856Specify outcome conditionals differently depending on the type of the outcome variable:
857 
858* **integer**: compare against an integer literal with operators `=, >, >=, <, <=, !=`, for example:
859 
860 `$risk_score > 10`
861* **float**: compare against a float literal with operators `=, >, >=, <, <=, !=`, for example:
862 
863 `$risk_score <= 5.5`
864* **string**: compare against a string literal with either `=` or `!=`, for example:
865 
866 `$severity = "HIGH"`
867* **list of integers or arrays**: specify condition using the `arrays.contains` function, for example:
868 
869 `arrays.contains($event_ids, "id_1234")`
870 
871**Note:** If you use the keyword `or` inside the <event/placeholder conditionals> subsection, you must surround that entire subsection with parentheses.
872For example, the following is valid: `($e1 or $e2) and $outcome > 0`.
873 
874#### Rule classification
875 
876Specifying an outcome conditional *in a rule that has a match section* means that the rule will be classified as a **multi-event** rule for rule quota.
877See [single event rule](/chronicle/docs/detection/yara-l-2-0-overview#single_event_rule) and [multiple event rule](/chronicle/docs/detection/yara-l-2-0-overview#multiple_event_rule) for more information about single and multiple event classifications.
878 
879## Options section syntax
880 
881In the `options` section, you can specify the options for the rule. Here is
882an example of how to specify the options section:
883 
884```
885rule RuleOptionsExample {
886 // Other rule sections
887 
888 options:
889 allow_zero_values = true
890}
891 
892```
893 
894You can specify options using the syntax `key = value`, where `key` must be a
895predefined option name and `value` must be a valid value for the option, as
896specified for the following options:
897 
898### allow\_zero\_values
899 
900The valid values for this option are `true` and `false`, which determine
901if this option is enabled or not. The default value is `false`. This option is
902disabled if it is not specified in the rule.
903 
904To enable this setting, add the following
905to the options section of your rule: `allow_zero_values = true`. Doing so
906will prevent the rule from implicitly filtering out the
907zero values of placeholders that are used in the match section, as
908described in [zero value handling in the match section](#zero_value_handling_in_the_match_section).
909 
910### suppression\_window
911 
912The `suppression_window` option lets you control how often a rule triggers a
913detection. It prevents the same rule from generating multiple detections within
914a specified time window, even if the rule's conditions are met multiple times.
915Suppression windowing uses a tumbling window approach, which suppresses
916duplicates over a fixed-size, non-overlapping window.
917 
918You can optionally provide a `suppression_key` to further refine which instances
919of the rule are suppressed within the suppression window. If not specified, all
920instances of the rule are suppressed. This key is defined as an outcome variable.
921 
922In the following example, `suppression_window` is set to `5m` and `suppression_key` is
923set to the `$hostname` variable. After the rule triggers a detection for
924`$hostname`, any further detections for `$hostname` are suppressed for the next
925five minutes. However, if the rule triggers on an event with a different hostname,
926a detection is created.
927 
928The default value of `suppression_window` is `0`; that is, the suppression
929window is disabled by default. This option only works for [single event rules](/chronicle/docs/detection/yara-l-2-0-overview#single-event-rule)
930that don't have a `match` section.
931 
932Example:
933 
934```
935rule SuppressionWindowExample {
936 // Other rule sections
937 
938 outcome:
939 $suppression_key = $hostname
940 
941 options:
942 suppression_window = 5m
943}
944 
945```
946 
947## Composite detection rules
948 
949**Note:** This feature is covered by [Pre-GA Offerings Terms](https://chronicle.security/legal/service-terms/) of the Google Security Operations Service
950Specific Terms. Pre-GA features might have limited support, and changes to pre-GA features might not be compatible with other pre-GA versions.
951For more information, see the [Google SecOps Technical Support Service guidelines](https://chronicle.security/legal/technical-support-services-guidelines/)
952and the [Google SecOps Service Specific Terms](https://chronicle.security/legal/service-terms/).
953 
954Composite detection in Google SecOps involves connecting multiple
955YARA-L rules. This sections explains how to build a
956composite rule. For an overview of composite detections,
957see [Overview of composite detections](/chronicle/docs/detection/composite-detections).
958 
959### Rule structure
960 
961Composite detection rules are always multi-event rules and follow the same
962[structure and syntax](/chronicle/docs/detection/yara-l-2-0-syntax#rule_structure).
963The following requirements apply to composite detection rules:
964 
965* Composite rules must use a `match` section to define detection trigger conditions.
966* Rules that use both detection fields and UDM events must explicitly join these
967 data sources.
968 
969For information on rule limitations, see [Limitations](/chronicle/docs/detection/composite-detections#limitations).
970 
971### Use detections as input to rules
972 
973Composite rules can reference rule detections generated by any custom or curated rule.
974Google SecOps provides two methods for doing this.
975 
976#### Reference detection content using outcome variables, match variables, or meta labels
977 
978To access data from a detection without referencing the original UDM events,
979use `outcome` variables, `match` variables, or `meta` labels. We recommend this
980approach because it provides greater flexibility and better compatibility across
981different rule types.
982 
983For example, multiple rules can store a string (such as a URL, filename, or
984registry key) in a common `outcome` variable if you're looking for that string
985across different contexts. To access this string from a composite rule, start
986with `detection` and locate the relevant information using elements from the
987[Collection resource](/chronicle/docs/reference/rest/v1alpha/Collection).
988 
989**Example:**
990For example, suppose a detection rule produces the following information:
991 
992* Outcome variable: `dest_domain = "cymbal.com"`
993* UDM field: `target.hostname = "cymbal.com"`
994 
995In the composite rule, you can access this data using the following paths:
996 
997* `detection.detection.outcomes["dest_domain"]` to access the `dest_domain`
998 outcome variable.
999* `detection.collection_elements.references.event.target.hostname` to access
1000 the `target.hostname` UDM field.
1001* `detection.time_window.start_time.seconds` to access the detection timestamp.
1002 
1003The Collection API and the `SecurityResult` API provide access to both:
1004 
1005* Detection metadata and outcome values (`detection.detection`)
1006* Underlying UDM events from referenced rules (`collection_elements`)
1007 
1008#### Reference detection content using rule ID or rule name
1009 
1010You can reference a rule by either its name or ID. We recommend this
1011approach when your detection logic depends on specific rules. Referencing
1012relevant rules by name or ID improves performance and prevents timeouts by
1013reducing the data analyzed. For example, you can directly query fields like
1014`target.url` or `principal.ip` from a known previous detection.
1015 
1016* **Reference a rule by rule ID (recommended):** use the
1017 `detection.detection.rule_id` field to reference a rule by ID. You can find the
1018 rule ID in the rule's URL in Google SecOps. User-generated rules
1019 have IDs in the format `ru_UUID`, while curated detections have IDs in the
1020 format `ur_UUID`. For example:
1021 
1022 `detection.detection.rule_id = "ru_e0d3f371-6832-4d20-b0ad-1f4e234acb2b"`
1023* **Reference a rule by a rule name:** use the `detection.detection.rule_name`
1024 field to reference a rule by name. You can specify the exact rule name or use a
1025 regular expression to match it. For example:
1026 
1027 + `detection.detection.rule_name = "My Rule Name"`
1028 + `detection.detection.rule_name = "/PartOfName/"`
1029 
1030**Note:** We recommend using rule IDs for referencing because IDs are unique and
1031don't change. Rule names can be modified, which could potentially break your
1032composite detection.
1033 
1034### Combine events and detections
1035 
1036Composite rules can combine different data sources, including UDM events, entity
1037graph data, and detection fields. The following guidelines apply:
1038 
1039* **Use distinct variables per source**—Assign unique event variables to each data source (for example, `$e` for
1040 events, `$d` for detections), where the data source includes events, entities,
1041 and detections.
1042* **Join sources on shared context**—Connect data sources using common values, such as user IDs, IP addresses, or
1043 domain names in your rule's conditions.
1044* **Define a match window**—Always include a `match` clause with a time window no longer than 48 hours.
1045 
1046For example:
1047 
1048```
1049rule CheckCuratedDetection_with_EDR_and_EG {
1050 meta:
1051 author = "noone@cymbal.com"
1052 events:
1053 $d.detection.detection.rule_name = /SCC: Custom Modules: Configurable Bad Domain/
1054 $d.detection.collection_elements.references.event.network.dns.questions.name = $domain
1055 $d.detection.collection_elements.references.event.principal.asset.hostname = $hostname
1056 
1057 $e.metadata.log_type = "LIMACHARLIE_EDR"
1058 $e.metadata.product_event_type = "NETWORK_CONNECTIONS"
1059 $domain = re.capture($e.principal.process.command_line, "\\s([a-zA-Z0-9.-]+\\.[a-zA-Z0-9.-]+)$")
1060 $hostname = re.capture($e.principal.hostname, "([^.]*)")
1061 
1062 $prevalence.graph.metadata.entity_type = "DOMAIN_NAME"
1063 $prevalence.graph.metadata.source_type = "DERIVED_CONTEXT"
1064 $prevalence.graph.entity.hostname = $domain
1065 $prevalence.graph.entity.domain.prevalence.day_count = 10
1066 $prevalence.graph.entity.domain.prevalence.rolling_max <= 5
1067 $prevalence.graph.entity.domain.prevalence.rolling_max > 0
1068 
1069 match:
1070 $hostname over 1h
1071 
1072 outcome:
1073 $risk_score = 80
1074 $CL_target = array($domain)
1075 
1076 condition:
1077 $e and $d and $prevalence
1078}
1079 
1080```
1081 
1082### Create sequential composite detections
1083 
1084Sequential composite detections identify patterns of related events where the
1085sequence of detections is important, such as a brute-force login attempt
1086detection, followed by a successful login. These patterns can combine multiple
1087base detections, raw UDM events, or both.
1088 
1089To create a sequential composite detection, you must enforce that order within
1090your rule. To enforce the expected sequence, use one of the following methods:
1091 
1092* **Sliding windows:** Define the sequence of detections using sliding windows
1093 in your `match` conditions.
1094* **Timestamp comparisons:** Compare the timestamps of detections within your
1095 rule logic to ensure that they happen in the selected order.
1096 
1097For example:
1098 
1099```
1100events:
1101 $d1.detection.detection.rule_name = "fileEvent_rule"
1102 $userid = $d1.detection.detection.outcomes["user"]
1103 $hostname = $d1.detection.detection.outcomes["hostname"]
1104 
1105 $d2.detection.detection.rule_name = "processExecution_rule"
1106 $userid = $d2.detection.detection.outcomes["user"]
1107 $hostname = $d2.detection.detection.outcomes["hostname"]
1108 
1109 $d3.detection.detection.rule_name = "networkEvent_rule"
1110 $userid = $d3.detection.detection.outcomes["user"]
1111 $hostname = $d3.detection.detection.outcomes["hostname"]
1112 
1113$d3.detection.collection_elements.references.event.metadata.event_timestamp.seconds > $d2.detection.collection_elements.references.event.metadata.event_timestamp.seconds
1114 
1115 match:
1116 $userid over 24h after $d1
1117 
1118```
1119 
1120## Boolean expressions
1121 
1122Boolean expressions are expressions with a boolean type.
1123 
1124### Comparisons
1125 
1126For a binary expression to use as condition, use the following syntax:
1127 
1128* `<EXPR> <OP> <EXPR>`
1129 
1130Expression can be either event field, variable, literal, or function expression.
1131 
1132For example:
1133 
1134* `$e.source.hostname = "host1234"`
1135* `$e.source.port < 1024`
1136* `1024 < $e.source.port`
1137* `$e1.source.hostname != $e2.target.hostname`
1138* `$e1.metadata.collected_timestamp.seconds > $e2.metadata.collected_timestamp.seconds`
1139* `$port >= 25`
1140* `$host = $e2.target.hostname`
1141* `"google-test" = strings.concat($e.principal.hostname, "-test")`
1142* `"email@google.org" = re.replace($e.network.email.from, "com", "org")`
1143 
1144If both sides are literals, it is regarded as a compilation error.
1145 
1146### Functions
1147 
1148Some function expressions return boolean value, which can be used as an individual predicate in the `events` section. Such functions are:
1149 
1150* `re.regex()`
1151* `net.ip_in_range_cidr()`
1152 
1153For example:
1154 
1155* `re.regex($e.principal.hostname, `.*\.google\.com`)`
1156* `net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/24")`
1157 
1158### Reference list expressions
1159 
1160You can use reference lists in the events section. See the section on
1161[Reference Lists](#reference_lists_syntax) for more details.
1162 
1163### Logical expressions
1164 
1165You can use the logical `and` and logical `or` operators in the `events` section as shown in the following examples:
1166 
1167* `$e.metadata.event_type = "NETWORK_DNS" or $e.metadata.event_type = "NETWORK_DHCP"`
1168* `($e.metadata.event_type = "NETWORK_DNS" and $e.principal.ip = "192.0.2.12") or ($e.metadata.event_type = "NETWORK_DHCP" and $e.principal.mac = "AB:CD:01:10:EF:22")`
1169* `not $e.metadata.event_type = "NETWORK_DNS"`
1170 
1171By default, the precedence order from highest to lowest is `not`, `and`, `or`.
1172 
1173For example, "a or b and c" is evaluated as "a or (b and c)" when the operators `or` and `and` are defined explicitly in the expression.
1174 
1175In the `events` section, predicates are joined using the `and` operator if an operator is not explicitly defined.
1176 
1177The order of evaluation may be different if the `and` operator is implied in the expression.
1178 
1179For example, consider the following comparison expressions where `or` is defined explicitly. The `and` operator is implied.
1180 
1181```
1182$e1.field = "bat"
1183or $e1.field = "baz"
1184$e2.field = "bar"
1185 
1186```
1187 
1188This example is interpreted as follows:
1189 
1190```
1191($e1.field = "bat" or $e1.field = "baz")
1192and ($e2.field = "bar")
1193 
1194```
1195 
1196Because `or` is defined explicitly, the predicates surrounding `or` are grouped and evaluated first.
1197The last predicate, `$e2.field = "bar"` is joined implicitly using `and`. The result is that order of evaluation changes.
1198 
1199**Note:** There is a limit on the number of `and` and `or` values you can specify for a
1200single rule. This limit varies depending on the complexity of the rule and the
1201complexity of the data in your Google SecOps account. Contact your Google SecOps representative for information on alternatives to this type of
1202rule.
1203 
1204## Enumerated types
1205 
1206You can use the operators with [enumerated](/chronicle/docs/reference/udm-field-list#event_enumerated_types) types. It can be applied to rules to simplify and optimize (use operator instead of reference lists) the performance.
1207 
1208In the following example, 'USER\_UNCATEGORIZED' and 'USER\_RESOURCE\_DELETION' correspond to 15000 and 15014, so the rule will look for all the listed events:
1209 
1210```
1211$e.metadata.event_type >= "USER_CATEGORIZED" and $e.metadata.event_type <= "USER_RESOURCE_DELETION"
1212 
1213```
1214 
1215List of events:
1216 
1217* USER\_RESOURCE\_DELETION
1218* USER\_RESOURCE\_UPDATE\_CONTENT
1219* USER\_RESOURCE\_UPDATE\_PERMISSIONS
1220* USER\_STATS
1221* USER\_UNCATEGORIZED
1222 
1223## Nocase Modifier
1224 
1225When you have a comparison expression between string values or a regular expression, you can append nocase at the end of the expression to ignore capitalization.
1226 
1227* `$e.principal.hostname != "http-server" nocase`
1228* `$e1.principal.hostname = $e2.target.hostname nocase`
1229* `$e.principal.hostname = /dns-server-[0-9]+/ nocase`
1230* `re.regex($e.target.hostname, `client-[0-9]+`) nocase`
1231 
1232This cannot be used when a type of field is an enumerated value. The following
1233examples are invalid and will generate compilation errors:
1234 
1235* `$e.metadata.event_type = "NETWORK_DNS" nocase`
1236* `$e.network.ip_protocol = "TCP" nocase`
1237 
1238## Repeated fields
1239 
1240In the Unified Data Model (UDM), some fields are labeled as repeated, which indicates
1241that they are lists of values or other types of messages.
1242 
1243### Repeated fields and boolean expressions
1244 
1245There are 2 kinds of boolean expressions that act on repeated fields:
1246 
12471. Modified
12482. Unmodified
1249 
1250Consider the following event:
1251 
1252```
1253event_original {
1254 principal {
1255 // ip is a repeated field
1256 ip: [ "192.0.2.1", "192.0.2.2", "192.0.2.3" ]
1257 
1258 hostname: "host"
1259 }
1260}
1261 
1262```
1263 
1264#### Modified expressions
1265 
1266The following sections describe the purpose and how to use the `any` and `all` modifiers in expressions.
1267 
1268##### any
1269 
1270If *any* element of the repeated field satisfies the condition, the event as a whole satisfies the condition.
1271 
1272* `event_original` satisfies `any $e.principal.ip = "192.0.2.1"`.
1273* `event_original` fails `any $e.repeated_field.field_a = "9.9.9.9`.
1274 
1275##### all
1276 
1277If *all* elements of the repeated field satisfy the condition, the event as a whole satisfies the condition.
1278 
1279* `event_original` satisfies `net.ip_in_range_cidr(all $e.principal.ip, "192.0.2.0/8")`.
1280* `event_original` fails `all $e.principal.ip = "192.0.2.2"`.
1281 
1282**Note:** To use `any` or `all` with a function, the modifier must precede the repeated field and not the function. For example, `re.regex(any $e.about.hostname, `server-[0-9]+`)` is valid while `any re.regex($e.about.hostname, `server-[0-9]+`)` is not.
1283 
1284When writing a condition with `any` or `all`, be aware that negating the condition
1285with `not` might not have the same meaning as using the negated operator.
1286 
1287For example:
1288 
1289* `not all $e.principal.ip = "192.168.12.16"` checks if not all IP addresses
1290 match `192.168.12.16`, meaning the rule is checking whether at least one IP address
1291 does not match `192.168.12.16`.
1292* `all $e.principal.ip != "192.168.12.16"` checks if all IP addresses don't match
1293 `192.168.12.16`, meaning the rule is checking that no IP addresses match to `192.168.12.16`.
1294 
1295Constraints:
1296 
1297* `any` and `all` operators are only compatible with repeated fields (not scalar fields).
1298* `any` and `all` cannot be used to join two repeated fields. For example, `any $e1.principal.ip = $e2.principal.ip` is not valid.
1299* `any` and `all` operators are not supported with the reference list expression.
1300 
1301#### Unmodified expressions
1302 
1303With unmodified expressions, each element in the repeated field is treated individually. If an event's repeated field contains *n* elements, then the rule is applied on *n* copies of the event, where each copy has one of the elements of the repeated field. These copies are transient and not stored.
1304 
1305The rule is applied on the following copies:
1306 
1307| event copy | principal.ip | principal.hostname |
1308| --- | --- | --- |
1309| event\_copy\_1 | "192.0.2.1" | "host" |
1310| event\_copy\_2 | "192.0.2.2" | "host" |
1311| event\_copy\_3 | "192.0.2.3" | "host" |
1312 
1313If *any* event copy satisfies *all* unmodified conditions on the repeated field, the event as a whole satisfies all the conditions. That means that if you have multiple conditions on a repeated field, then the event copy must satisfy *all* of them. The following rule examples use the preceding example dataset to demonstrate this behavior.
1314 
1315The following rule returns one match when run against the `event_original` example
1316dataset, because `event_copy_1` satisfies all of the events predicates:
1317 
1318```
1319rule repeated_field_1 {
1320 meta:
1321 events:
1322 net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/8") // Checks if IP address matches 192.x.x.x
1323 $e.principal.ip = "192.0.2.1"
1324 condition:
1325 $e
1326}
1327 
1328```
1329 
1330The following rule doesn't return a match when run against the `event_original`
1331example dataset, because there is no event copy in `$e.principal.ip` that
1332satisfies *all* the event predicates.
1333 
1334```
1335rule repeated_field_2 {
1336 meta:
1337 events:
1338 $e.principal.ip = "192.0.2.1"
1339 $e.principal.ip = "192.0.2.2"
1340 condition:
1341 $e
1342}
1343 
1344```
1345 
1346Modified expressions on repeated fields are compatible with unmodified expressions on repeated fields because the element list is the same for each event copy. Consider the following rule:
1347 
1348```
1349rule repeated_field_3 {
1350 meta:
1351 events:
1352 any $e.principal.ip = "192.0.2.1"
1353 $e.principal.ip = "192.0.2.3"
1354 condition:
1355 $e
1356}
1357 
1358```
1359 
1360The rule is applied on the following copies:
1361 
1362| event copy | principal.ip | any $e.principal.ip |
1363| --- | --- | --- |
1364| event\_copy\_1 | "192.0.2.1" | ["192.0.2.1", "192.0.2.2", "192.0.2.3"] |
1365| event\_copy\_2 | "192.0.2.2" | ["192.0.2.1", "192.0.2.2", "192.0.2.3"] |
1366| event\_copy\_3 | "192.0.2.3" | ["192.0.2.1", "192.0.2.2", "192.0.2.3"] |
1367 
1368In this case, all copies satisfy `any $e.principal.ip = "192.0.2.1"` but only `event_copy_3` satisfies $e.principal.ip = "192.0.2.3". As a result, the event as a whole would match.
1369 
1370Another way to think about these expression types are:
1371 
1372* Expressions on repeated fields which use `any` or `all` operate on the list in `event_original`.
1373* Expressions on repeated fields which don't use `any` or `all` operate on individual `event_copy_n` events.
1374 
1375### Repeated fields and placeholders
1376 
1377Repeated fields work with placeholder assignments. Similar to unmodified expressions on repeated fields, a copy of the event is made for each element. Using the same example of `event_copy`, the placeholder takes the value of the `event_copy_n`'s repeated field value, for each of the event copies where *n* is the event copy number. If the placeholder is used in the match section, this can result in multiple matches.
1378 
1379The following example generates one match. The `$ip` placeholder is equal
1380to `192.0.2.1` for `event_copy_1`, which satisfies the predicates in the rule.
1381The match's event samples contain a single element, `event_original`.
1382 
1383```
1384// Generates 1 match.
1385rule repeated_field_placeholder1 {
1386 meta:
1387 events:
1388 $ip = $e.principal.ip
1389 $ip = "192.0.2.1"
1390 $host = $e.principal.hostname
1391 
1392 match:
1393 $host over 5m
1394 
1395 condition:
1396 $e
1397}
1398 
1399```
1400 
1401The following example generates three matches. The `$ip` placeholder is equal
1402to different values, for each of the different `event_copy_n` copies.
1403The grouping is done on `$ip` since it is in the match section. Therefore, you get three matches
1404where each match has a different value for the `$ip` match variable. Each match has the same
1405event sample: a single element, `event_original`.
1406 
1407```
1408// Generates 3 matches.
1409rule repeated_field_placeholder2 {
1410 meta:
1411 events:
1412 $ip = $e.principal.ip
1413 net.ip_in_range_cidr($ip, "192.0.2.0/8") // Checks if IP matches 192.x.x.x
1414 
1415 match:
1416 $ip over 5m
1417 
1418 condition:
1419 $e
1420}
1421 
1422```
1423 
1424**Note:** `any` and `all` cannot be used when assigning a repeated field to a placeholder variable or joining with a field of another event. For example, `any $e.principal.ip = $ip` is not valid.
1425 
1426#### Outcomes using placeholders assigned to repeated fields
1427 
1428Placeholders are assigned to each *element* of each repeated field - not the entire list. Thus, when they're used in the outcome section, the outcome is calculated using only the elements that satisfied earlier sections.
1429 
1430Consider the following rule:
1431 
1432```
1433rule outcome_repeated_field_placeholder {
1434 meta:
1435 events:
1436 $ip = $e.principal.ip
1437 $ip = "192.0.2.1" or $ip = "192.0.2.2"
1438 $host = $e.principal.hostname
1439 
1440 match:
1441 $host over 5m
1442 
1443 outcome:
1444 $o = array_distinct($ip)
1445 
1446 condition:
1447 $e
1448}
1449 
1450```
1451 
1452There are 4 stages of execution for this rule. The first stage is event copying:
1453 
1454| event copy | $ip | $host | $e |
1455| --- | --- | --- | --- |
1456| event\_copy\_1 | "192.0.2.1" | "host" | event\_id |
1457| event\_copy\_2 | "192.0.2.2" | "host" | event\_id |
1458| event\_copy\_3 | "192.0.2.3" | "host" | event\_id |
1459 
1460The events section will then filter out rows that don't match the filters:
1461 
1462| event copy | $ip | $host | $e |
1463| --- | --- | --- | --- |
1464| event\_copy\_1 | "192.0.2.1" | "host" | event\_id |
1465| event\_copy\_2 | "192.0.2.2" | "host" | event\_id |
1466 
1467`event_copy_3` is filtered out because `"192.0.2.3"` does not satisfy `$ip = "192.0.2.1" or $ip = "192.0.2.2"`.
1468 
1469The match section will then group by match variables and the outcome section will perform aggregation on each group:
1470 
1471| $host | $o | $e |
1472| --- | --- | --- |
1473| "host" | ["192.0.2.1", "192.0.2.2"] | event\_id |
1474 
1475`$o = array_distinct($ip)` is calculated using `$ip` from the previous stage and not the event copying stage.
1476 
1477Finally, the condition section will filter each group. Since this rule just checks for the existence of $e, the row from earlier will produce a single detection.
1478 
1479`$o` does not contain all the elements from `$e.principal.ip` because not all the elements satisfied all the conditions in the events section. However, all the elements of `e.principal.ip` will appear in the event sample because the event sample uses `event_original`.
1480 
1481### Array indexing
1482 
1483You can perform array indexing on repeated fields. To access the n-th repeated field element, use the standard list syntax (elements are 0-indexed). An out-of-bounds element returns the default value.
1484 
1485* `$e.principal.ip[0] = "192.168.12.16"`
1486* `$e.principal.ip[999] = ""` If there are fewer than 1000 elements, this evaluates to `true`.
1487 
1488Constraints:
1489 
1490* An index must be a non-negative integer literal. For example, `$e.principal.ip[-1]` is not valid.
1491* Values that have an `int` type (for example, a placeholder set to `int`) don't count.
1492* Array indexing cannot be combined with `any` or `all`. For example, `any $e.intermediary.ip[0]` is not valid.
1493* Array indexing cannot be combined with map syntax. For example, `$e.additional.fields[0]["key"]` is not valid.
1494* If the field path contains multiple repeated fields, all repeated fields must use array indexing. For example, `$e.intermediary.ip[0]` is not valid because `intermediary` and `ip` are both repeated fields, but there is only an index for `ip`.
1495 
1496### Repeated messages
1497 
1498When a [`message`](https://protobuf.dev/overview/#syntax) field is repeated, an unintended effect is to reduce the likelihood of a match. This is illustrated in the following examples.
1499 
1500Consider the following event:
1501 
1502```
1503event_repeated_message {
1504 // about is a repeated message field.
1505 about {
1506 // ip is a repeated string field.
1507 ip: [ "192.0.2.1", "192.0.2.2", "192.0.2.3" ]
1508 
1509 hostname: "alice"
1510 }
1511 about {
1512 hostname: "bob"
1513 }
1514}
1515 
1516```
1517 
1518As stated for unmodified expressions on repeated fields, a temporary copy of the event is made for each element of the repeated field. Consider the following rule:
1519 
1520```
1521rule repeated_message_1 {
1522 meta:
1523 events:
1524 $e.about.ip = "192.0.2.1"
1525 $e.about.hostname = "bob"
1526 condition:
1527 $e
1528}
1529 
1530```
1531 
1532The rule is applied on the following copies:
1533 
1534| event copy | about.ip | about.hostname |
1535| --- | --- | --- |
1536| event\_copy\_1 | "192.0.2.1" | "alice" |
1537| event\_copy\_2 | "192.0.2.2" | "alice" |
1538| event\_copy\_3 | "192.0.2.3" | "alice" |
1539| event\_copy\_4 | "" | "bob" |
1540 
1541The event does not match on the rule because there exists no event copy that satisfies all of the expressions.
1542 
1543#### Repeated messages and array indexing
1544 
1545Another unexpected behavior can occur when using array indexing with unmodified expressions on repeated message fields. Consider the following example rule which uses array indexing:
1546 
1547```
1548rule repeated_message_2 {
1549 meta:
1550 events:
1551 $e.about.ip = "192.0.2.1"
1552 $e.about[1].hostname = "bob"
1553 condition:
1554 $e
1555}
1556 
1557```
1558 
1559The rule is applied to the following copies:
1560 
1561| event copy | about.ip | about[1].hostname |
1562| --- | --- | --- |
1563| event\_copy\_1 | "192.0.2.1" | "bob" |
1564| event\_copy\_2 | "192.0.2.2" | "bob" |
1565| event\_copy\_3 | "192.0.2.3" | "bob" |
1566| event\_copy\_4 | "" | "bob" |
1567 
1568Since `event_copy_1` satisfies all of the expressions in `repeated_message_2`, the event matches on the rule.
1569 
1570This can lead to unexpected behavior because rule `repeated_message_1` lacked array indexing and produced no matches while rule `repeated_message_2` used array indexing and produced a match.
1571 
1572## Comments
1573 
1574Designate comments with two slash characters (`// comment`) or multi-line comments set off using slash asterisk characters (`/* comment */`), as you would in C.
1575 
1576## Literals
1577 
1578Nonnegative integers and floats, string, boolean, and regular expression literals are supported.
1579 
1580### String and regular expression literals
1581 
1582You can use either of the following quotation characters to enclose strings in YARA-L 2.0. However, quoted text is interpreted differently depending on which one you use.
1583 
15841. Double quotes (") — Use for normal strings. Must include escape characters.
1585 For example: "hello\tworld" —\t is interpreted as a tab
15862. Back quotes (`) — Use to interpret all characters literally.
1587 For example: `hello\tworld` —\t is not interpreted as a tab
1588 
1589For regular expressions, you have two options.
1590 
1591If you want to use regular expressions directly without the `re.regex()` function, use `/regex/` for the regular expression literals.
1592 
1593You can also use string literals as regular expression literals when you use the `re.regex()` function. Note that for double quote string literals, you must escape backslash characters with backslash characters, which can look awkward.
1594 
1595For example, the following regular expressions are equivalent:
1596 
1597* `re.regex($e.network.email.from, `.*altostrat\.com`)`
1598* `re.regex($e.network.email.from, ".*altostrat\\.com")`
1599* `$e.network.email.from = /.*altostrat\.com/`
1600 
1601Google recommends using back quote characters for strings in regular expressions for ease of readability.
1602 
1603## Operators
1604 
1605You can use the following operators in YARA-L:
1606 
1607| | |
1608| --- | --- |
1609| **Operator** | **Description** |
1610| = | equal/declaration |
1611| != | not equal |
1612| < | less than |
1613| <= | less than or equal |
1614| > | greater than |
1615| >= | greater than or equal |
1616 
1617## Variables
1618 
1619In YARA-L 2.0, all variables are represented as `$<variable name>`.
1620 
1621You can define the following types of variables:
1622 
1623* Event variables — Represent groups of events in normalized form (UDM) or entity events. Specify conditions for event variables in the `events` section. You identify event variables using a name, event source, and event fields. Allowed sources are `udm` (for normalized events) and `graph` (for entity events). If the source is omitted, `udm` is set as the default source. Event fields are represented as a chain of *.<field name>* (for example, *$e.field1.field2*). Event field chains always start from the top-level source (UDM or Entity).
1624* Match variables — Declare in the `match` section. Match variables become grouping fields for the query, as one row is returned for each unique set of match variables (and for each time window). When the rule finds a match, the match variable values are returned. Specify what each match variable represents in the `events` section.
1625* Placeholder variables — Declare and define in the `events` section. Placeholder variables are similar to match variables. However, you can use placeholder variables in the `condition` section to specify match conditions.
1626 
1627**Note:** Every placeholder variable **must** be mapped to an event field. For example, if you only referenced the following placeholder in this single line in a rule, it would fail to compile since *$var* is not bound to an event variable: *$e.field != $var*
1628 
1629Use match variables and placeholder variables to declare relationships between event fields through transitive join conditions (see [Events Section Syntax](#events_section_syntax) for more detail).
1630 
1631## Keywords
1632 
1633Keywords in YARA-L 2.0 are case-insensitive. For example, `and` or `AND` are
1634equivalent. Variable names must not conflict with keywords. For example,
1635`$AND` or `$outcome` is invalid.
1636 
1637The following are keywords for detection engine rules: `rule`, `meta`, `match`, `over`, `events`, `condition`, `outcome`, `options`, `and`, `or`, `not`, `nocase`, `in`, `regex`, `cidr`, `before`, `after`, `all`, `any`, `if`, `max`, `min`, `sum`, `array`, `array_distinct`, `count`, `count_distinct`, `is`, and `null`.
1638 
1639### Maps
1640 
1641YARA-L supports map access for Structs and Labels.
1642 
1643#### Structs and Labels
1644 
1645Some UDM fields use either the [Struct](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#struct) or [Label](/chronicle/docs/reference/udm-field-list#label) data type.
1646 
1647To search for a specific key-value pair in both Struct and Label, use the standard map syntax:
1648 
1649```
1650// A Struct field.
1651$e.udm.additional.fields["pod_name"] = "kube-scheduler"
1652// A Label field.
1653$e.metadata.ingestion_labels["MetadataKeyDeletion"] = "startup-script"
1654 
1655```
1656 
1657The map access always returns a string.
1658 
1659#### Supported cases
1660 
1661##### Events and Outcome Section
1662 
1663```
1664// Using a Struct field in the events section
1665events:
1666 $e.udm.additional.fields["pod_name"] = "kube-scheduler"
1667 
1668// Using a Label field in the outcome section
1669outcome:
1670 $value = array_distinct($e.metadata.ingestion_labels["MetadataKeyDeletion"])
1671 
1672```
1673 
1674##### Assigning a map value to a Placeholder
1675 
1676```
1677$placeholder = $u1.metadata.ingestion_labels["MetadataKeyDeletion"]
1678 
1679```
1680 
1681##### Using a map field in a join condition
1682 
1683```
1684// using a Struct field in a join condition between two udm events $u1 and $u2
1685$u1.metadata.event_type = $u2.udm.additional.fields["pod_name"]
1686 
1687```
1688 
1689#### Unsupported cases
1690 
1691Maps are not supported in the following cases.
1692 
1693##### Combining `any` or `all` keywords with a map
1694 
1695For example, the following is not supported:
1696 
1697```
1698all $e.udm.additional.fields["pod_name"] = "kube-scheduler"
1699 
1700```
1701 
1702##### Other types of values
1703 
1704The map syntax can only return a string value. In the case of
1705[Struct](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#struct)
1706data types, the map syntax can only access keys whose values are strings.
1707Accessing keys whose values are other primitive types like integers, is not possible.
1708 
1709#### Duplicate value handling
1710 
1711Map accesses always returns a single value. In the uncommon
1712edge case that the map access could refer to multiple values, the map
1713access will deterministically return the first value.
1714 
1715This can happen in either of the following cases:
1716 
1717* A label has a duplicate key.
1718 
1719 The label structure represents a map, but does not enforce key uniqueness.
1720 By convention, a map should have unique keys, so Google SecOps does
1721 not recommend populating a label with duplicate keys.
1722 
1723 The rule text `$e.metadata.ingestion_labels["dupe-key"]` would return
1724 the first possible value, `val1`, if run over the following data example:
1725 
1726```
1727 // Disrecommended usage of label with a duplicate key:
1728 event {
1729 metadata{
1730 ingestion_labels{
1731 key: "dupe-key"
1732 value: "val1" // This is the first possible value for "dupe-key"
1733 }
1734 ingestion_labels{
1735 key: "dupe-key"
1736 value: "val2"
1737 }
1738 }
1739 }
1740 
1741```
1742* A label has an ancestor repeated field.
1743 
1744 A repeated field might contain a label as a child field. Two different
1745 entries in the top-level repeated field might contain labels that
1746 have the same key. The rule text `$e.security_result.rule_labels["key"]`
1747 would return the first possible value, `val3`, if run over the following
1748 data example:
1749 
1750```
1751 event {
1752 // security_result is a repeated field.
1753 security_result {
1754 threat_name: "threat1"
1755 rule_labels {
1756 key: "key"
1757 value: "val3" // This is the first possible value for "key"
1758 }
1759 }
1760 security_result {
1761 threat_name: "threat2"
1762 rule_labels {
1763 key: "key"
1764 value: "val4"
1765 }
1766 }
1767 }
1768 
1769```
1770 
1771## Functions
1772 
1773This section describes the YARA-L 2.0 functions that you can use in detection
1774engine rules and search.
1775 
1776**Note:** The use of the event variable `$e` is optional when YARA-L is used in
1777search. Both `principal.hostname` and `$e.principal.hostname` are supported in
1778search.
1779 
1780These functions can be used in the following parts of a YARA-L rule:
1781 
1782* `events` section.
1783* `BOOL_CLAUSE` of a conditional in the [outcome section](#outcome_section_syntax).
1784 
1785### arrays.concat
1786 
1787Supported in:
1788 
1789[Rules](/chronicle/docs/detection/default-rules)
1790[Search](/chronicle/docs/investigation/udm-search)
1791 
1792```
1793arrays.concat(string_array, string_array)
1794 
1795```
1796 
1797#### Description
1798 
1799Returns a new string array by copying elements from original string arrays.
1800 
1801#### Param data types
1802 
1803`ARRAY_STRINGS`, `ARRAY_STRINGS`
1804 
1805#### Return type
1806 
1807`ARRAY_STRINGS`
1808 
1809#### Code samples
1810 
1811##### Example 1
1812 
1813The following example concatenates two different string arrays.
1814 
1815```
1816arrays.concat(["test1", "test2"], ["test3"]) = ["test1", "test2", "test3"]
1817 
1818```
1819 
1820##### Example 2
1821 
1822The following example concatenates arrays with empty string.
1823 
1824```
1825arrays.concat([""], [""]) = ["", ""]
1826 
1827```
1828 
1829##### Example 3
1830 
1831The following example concatenates empty arrays.
1832 
1833```
1834arrays.concat([], []) = []
1835 
1836```
1837 
1838 
1839 
1840### arrays.join\_string
1841 
1842Supported in:
1843 
1844[Rules](/chronicle/docs/detection/default-rules)
1845[Search](/chronicle/docs/investigation/udm-search)
1846 
1847```
1848arrays.join_string(array_of_strings, optional_delimiter)
1849 
1850```
1851 
1852#### Description
1853 
1854Converts an array of strings into a single string separated by the optional parameter. If no delimiter is provided, the empty string is used.
1855 
1856#### Param data types
1857 
1858`ARRAY_STRINGS`, `STRING`
1859 
1860#### Return type
1861 
1862`STRING`
1863 
1864#### Code samples
1865 
1866Here are some examples of how to use the function:
1867 
1868##### Example 1
1869 
1870This example joins an array with non-null elements and a delimiter.
1871 
1872```
1873arrays.join_string(["foo", "bar"], ",") = "foo,bar"
1874 
1875```
1876 
1877##### Example 2
1878 
1879This example joins an array with a null element and a delimiter.
1880 
1881```
1882arrays.join_string(["foo", NULL, "bar"], ",") = "foo,bar"
1883 
1884```
1885 
1886##### Example 3
1887 
1888This example joins an array with non-null elements and no delimiter.
1889 
1890```
1891arrays.join_string(["foo", "bar"]) = "foobar"
1892 
1893```
1894 
1895 
1896 
1897### arrays.length
1898 
1899Supported in:
1900 
1901[Rules](/chronicle/docs/detection/default-rules)
1902[Search](/chronicle/docs/investigation/udm-search)
1903 
1904```
1905arrays.length(repeatedField)
1906 
1907```
1908 
1909#### Description
1910 
1911Returns the number of repeated field elements.
1912 
1913#### Param data types
1914 
1915`LIST`
1916 
1917#### Return type
1918 
1919`NUMBER`
1920 
1921#### Code samples
1922 
1923##### Example 1
1924 
1925Returns the number of repeated field elements.
1926 
1927```
1928arrays.length($e.principal.ip) = 2
1929 
1930```
1931 
1932##### Example 2
1933 
1934If multiple repeated fields are along the path, returns the total number of repeated field elements.
1935 
1936```
1937arrays.length($e.intermediary.ip) = 3
1938 
1939```
1940 
1941 
1942 
1943### arrays.max
1944 
1945Supported in:
1946 
1947[Rules](/chronicle/docs/detection/default-rules)
1948[Search](/chronicle/docs/investigation/udm-search)
1949 
1950```
1951arrays.max(array_of_ints_or_floats)
1952 
1953```
1954 
1955#### Description
1956 
1957Returns the greatest element in an array or zero if the array is empty.
1958 
1959#### Param data types
1960 
1961`ARRAY_INTS|ARRAY_FLOATS`
1962 
1963#### Return type
1964 
1965`FLOAT`
1966 
1967#### Code samples
1968 
1969Here are some examples of how to use the function:
1970 
1971##### Example 1
1972 
1973This example returns the greater element in an array of integers.
1974 
1975```
1976arrays.max([10, 20]) = 20.000000
1977 
1978```
1979 
1980##### Example 2
1981 
1982This example returns the greater element in an array of floats.
1983 
1984```
1985arrays.max([10.000000, 20.000000]) = 20.000000
1986 
1987```
1988 
1989 
1990 
1991### arrays.min
1992 
1993Supported in:
1994 
1995[Rules](/chronicle/docs/detection/default-rules)
1996[Search](/chronicle/docs/investigation/udm-search)
1997 
1998```
1999arrays.min(array_of_ints_or_floats[, ignore_zeros=false])
2000 
2001```
2002 
2003#### Description
2004 
2005Returns the smallest element in an array or zero if the array is empty. If the
2006second, optional argument is set to true, elements equal to zero are ignored.
2007 
2008#### Param data types
2009 
2010`ARRAY_INTS|ARRAY_FLOATS`, `BOOL`
2011 
2012#### Return type
2013 
2014`FLOAT`
2015 
2016#### Code samples
2017 
2018Here are some examples of how to use the function:
2019 
2020##### Example 1
2021 
2022This example returns the smallest element in an array of integers.
2023 
2024```
2025arrays.min([10, 20]) = 10.000000
2026 
2027```
2028 
2029##### Example 2
2030 
2031This example returns the smallest element in an array of floats.
2032 
2033```
2034arrays.min([10.000000, 20.000000]) = 10.000000
2035 
2036```
2037 
2038##### Example 3
2039 
2040This example returns the smallest element in an array of floats, while ignoring the zeroes.
2041 
2042```
2043arrays.min([10.000000, 20.000000, 0.0], true) = 10.000000
2044 
2045```
2046 
2047 
2048 
2049### arrays.size
2050 
2051Supported in:
2052 
2053[Rules](/chronicle/docs/detection/default-rules)
2054[Search](/chronicle/docs/investigation/udm-search)
2055 
2056```
2057arrays.size( array )
2058 
2059```
2060 
2061#### Description
2062 
2063Returns the size of the array. Returns 0 for an empty array.
2064 
2065#### Param data types
2066 
2067`ARRAY_STRINGS|ARRAY_INTS|ARRAY_FLOATS`
2068 
2069#### Return type
2070 
2071`INT`
2072 
2073#### Code samples
2074 
2075##### Example 1
2076 
2077This example uses a string array that contains two elements.
2078 
2079```
2080arrays.size(["test1", "test2"]) = 2
2081 
2082```
2083 
2084##### Example 2
2085 
2086This example uses an int array that contains 3 elements.
2087 
2088```
2089arrays.size([1, 2, 3]) = 3
2090 
2091```
2092 
2093##### Example 3
2094 
2095This example uses a float array thats contains 1 elements
2096 
2097```
2098arrays.size([1.200000]) = 1
2099 
2100```
2101 
2102##### Example 4
2103 
2104This example uses an empty array.
2105 
2106```
2107arrays.size([]) = 0
2108 
2109```
2110 
2111 
2112 
2113### arrays.index\_to\_float
2114 
2115Supported in:
2116 
2117[Rules](/chronicle/docs/detection/default-rules)
2118[Search](/chronicle/docs/investigation/udm-search)
2119 
2120```
2121arrays.index_to_float(array, index)
2122 
2123```
2124 
2125#### Description
2126 
2127Returns the element at the given index of an array. The element at that index is returned as a float.
2128 
2129The index is an integer value which represents the position of an element in the array.
2130By default, the first element of an array has an index of 0, and the last element has an index of n-1, where n is the size of the array.
2131Negative indexing allows accessing array elements relative to the end of the array. For example, an index of -1 refers to the last element in the array and an index of -2 refers to the second to last element in the array.
2132 
2133#### Param data types
2134 
2135`ARRAY_STRINGS|ARRAY_INTS|ARRAY_FLOATS`, `INT`
2136 
2137#### Return type
2138 
2139`FLOAT`
2140 
2141#### Code samples
2142 
2143##### Example 1
2144 
2145The following example fetches an element at index 1 from an array of floats.
2146 
2147```
2148arrays.index_to_float([1.2, 2.1, 3.5, 4.6], 1) // 2.1
2149 
2150```
2151 
2152##### Example 2
2153 
2154The following example fetches an element at index -1 from an array of floats.
2155 
2156```
2157arrays.index_to_float([1.2, 2.1, 3.5, 4.6], 0-1) // 4.6
2158 
2159```
2160 
2161##### Example 3
2162 
2163The following example fetches an element for an index greater than the size of the array.
2164 
2165```
2166arrays.index_to_float([1.2, 2.1, 3.5, 4.6], 6) // 0.0
2167 
2168```
2169 
2170##### Example 4
2171 
2172The following example fetches an element from an empty array.
2173 
2174```
2175arrays.index_to_float([], 0) // 0.0
2176 
2177```
2178 
2179##### Example 5
2180 
2181The following example fetches an element at index 1 from a string array.
2182 
2183```
2184arrays.index_to_float(["1.2", "3.3", "2.4"], 1) // 3.3
2185 
2186```
2187 
2188##### Example 6
2189 
2190The following example fetches an element at index 2 from an array of integers.
2191 
2192```
2193arrays.index_to_float([1, 3, 2], 2) // 2.0
2194 
2195```
2196 
2197 
2198 
2199### arrays.index\_to\_int
2200 
2201Supported in:
2202 
2203[Rules](/chronicle/docs/detection/default-rules)
2204[Search](/chronicle/docs/investigation/udm-search)
2205 
2206```
2207arrays.index_to_int(array_of_inputs, index)
2208 
2209```
2210 
2211#### Description
2212 
2213Returns the value at a given index in an array as an integer.
2214 
2215The index is an integer value which represents the position of an element in the array.
2216By default, the first element of an array has an index of 0, and the last element has an index of n-1, where n is the size of the array.
2217Negative indexing allows accessing array elements relative to the end of the array. For example, an index of -1 refers to the last element in the array and an index of -2 refers to the second to last element in the array.
2218 
2219#### Param data types
2220 
2221`ARRAY_STRINGS|ARRAY_INTS|ARRAY_FLOATS`, `INT`
2222 
2223#### Return type
2224 
2225`INT`
2226 
2227#### Code samples
2228 
2229##### Example 1
2230 
2231This function call returns 0 when the value at the index is a non-numeric string.
2232 
2233```
2234arrays.index_to_int(["str0", "str1", "str2"], 1) = 0
2235 
2236```
2237 
2238##### Example 2
2239 
2240This function returns the element at index -1.
2241 
2242```
2243arrays.index_to_int(["44", "11", "22", "33"], 0-1) = 33
2244 
2245```
2246 
2247##### Example 3
2248 
2249Returns 0 for the out-of-bounds element.
2250 
2251```
2252arrays.index_to_int(["44", "11", "22", "33"], 5) = 0
2253 
2254```
2255 
2256##### Example 4
2257 
2258This function fetches the element from the float array at index 1.
2259 
2260```
2261arrays.index_to_int([1.100000, 1.200000, 1.300000], 1) = 1
2262 
2263```
2264 
2265##### Example 5
2266 
2267This function fetches the element from the int array at index 0.
2268 
2269```
2270arrays.index_to_int([1, 2, 3], 0) = 1
2271 
2272```
2273 
2274 
2275 
2276### arrays.index\_to\_str
2277 
2278Supported in:
2279 
2280[Rules](/chronicle/docs/detection/default-rules)
2281[Search](/chronicle/docs/investigation/udm-search)
2282 
2283```
2284arrays.index_to_str(array, index)
2285 
2286```
2287 
2288#### Description
2289 
2290Returns the element at the given index from the array as a string.
2291The index is an integer value that represents the position of an element in the array.
2292By default, the first element of an array has an index of 0, and the last element has an index of n-1, where n is the size of the array.
2293Negative indexing allows accessing array elements from the end of the array. For example, an index of -1 refers to the last element in the array and an index of -2 refers to the second to last element in the array.
2294 
2295#### Param data types
2296 
2297`ARRAY_STRINGS|ARRAY_INTS|ARRAY_FLOATS`, `INT`
2298 
2299#### Return type
2300 
2301`STRING`
2302 
2303#### Code samples
2304 
2305##### Example 1
2306 
2307The following example fetches an element at index 1 from an array of strings.
2308 
2309```
2310arrays.index_to_str(["test1", "test2", "test3", "test4"], 1) // "test2"
2311 
2312```
2313 
2314##### Example 2
2315 
2316The following example fetches an element at index -1 (last element of the array)
2317from an array of strings.
2318 
2319```
2320arrays.index_to_str(["test1", "test2", "test3", "test4"], 0-1) // "test4"
2321 
2322```
2323 
2324##### Example 3
2325 
2326The following example fetches an element for an index greater than the size of the array, which returns an empty string.
2327 
2328```
2329arrays.index_to_str(["test1", "test2", "test3", "test4"], 6) // ""
2330 
2331```
2332 
2333##### Example 4
2334 
2335The following example fetches an element from an empty array.
2336 
2337```
2338arrays.index_to_str([], 0) // ""
2339 
2340```
2341 
2342##### Example 5
2343 
2344The following example fetches an element at index 0 from an array of floats. The output is returned as a string.
2345 
2346```
2347arrays.index_to_str([1.200000, 3.300000, 2.400000], 0) // "1.2"
2348 
2349```
2350 
2351##### Example 6
2352 
2353The following example fetches an element at index 2 from an array of integers. The output is in the form of a string.
2354 
2355```
2356arrays.index_to_str([1, 3, 2], 2) // "2"
2357 
2358```
2359 
2360 
2361 
2362### cast.as\_bool
2363 
2364Supported in:
2365 
2366[Rules](/chronicle/docs/detection/default-rules)
2367[Search](/chronicle/docs/investigation/udm-search)
2368 
2369```
2370cast.as_bool(string_or_int)
2371 
2372```
2373 
2374#### Description
2375 
2376Function converts an int or string value into a bool value. Function calls with
2377values that cannot be casted will return FALSE. Returns TRUE only for integer 1
2378and case insensitive string 'true'.
2379 
2380#### Param data types
2381 
2382`INT|STRING`
2383 
2384#### Return type
2385 
2386`BOOL`
2387 
2388#### Code samples
2389 
2390##### Example 1
2391 
2392This example shows how to cast a non-boolean string
2393 
2394```
2395cast.as_bool("123") = false
2396 
2397```
2398 
2399##### Example 2
2400 
2401Truthy integer (1)
2402 
2403```
2404cast.as_bool(1) = true
2405 
2406```
2407 
2408##### Example 3
2409 
2410Truthy string
2411 
2412```
2413cast.as_bool("true") = true
2414 
2415```
2416 
2417##### Example 4
2418 
2419Capital truthy string
2420 
2421```
2422cast.as_bool("TRUE") = true
2423 
2424```
2425 
2426##### Example 5
2427 
2428Negative integer
2429 
2430```
2431cast.as_bool(0-1) = false
2432 
2433```
2434 
2435##### Example 6
2436 
2437False integer (0)
2438 
2439```
2440cast.as_bool(0) = false
2441 
2442```
2443 
2444##### Example 7
2445 
2446empty string
2447 
2448```
2449cast.as_bool("") = false
2450 
2451```
2452 
2453 
2454 
2455### cast.as\_float
2456 
2457Supported in:
2458 
2459[Rules](/chronicle/docs/detection/default-rules)
2460[Search](/chronicle/docs/investigation/udm-search)
2461 
2462```
2463cast.as_float(string_to_cast)
2464 
2465```
2466 
2467#### Description
2468 
2469Converts a numeric string into a float. Any function calls with values that
2470cannot be casted return 0. Floats maintain precision up to 7 decimal digits.
2471 
2472#### Param data types
2473 
2474`STRING`
2475 
2476#### Return type
2477 
2478`FLOAT`
2479 
2480#### Code samples
2481 
2482##### Example 1
2483 
2484Casting a non-numeric string returns 0.
2485 
2486```
2487cast.as_float("str") = 0.0000000
2488 
2489```
2490 
2491##### Example 2
2492 
2493Casting an empty string returns 0.
2494 
2495```
2496cast.as_float("") = 0.0000000
2497 
2498```
2499 
2500##### Example 3
2501 
2502Casting a valid numeric string returns a float value.
2503 
2504```
2505cast.as_float("1.012345678") = 1.0123456
2506 
2507```
2508 
2509 
2510 
2511### cast.as\_string
2512 
2513Supported in:
2514 
2515[Rules](/chronicle/docs/detection/default-rules)
2516[Search](/chronicle/docs/investigation/udm-search)
2517 
2518```
2519cast.as_string(int_or_bytes_or_bool, optional_default_string)
2520 
2521```
2522 
2523#### Description
2524 
2525The `cast.as_string` function transforms an `INT`, `BYTES`, or `BOOL` value into its string representation. You can provide an optional `default_string` argument to handle cases where the cast fails. If you omit the `default_string` argument, or if the input is an invalid `UTF-8` or `BASE64` byte sequence, the function returns an empty string.
2526 
2527#### Param data types
2528 
2529`INT|BYTES|BOOL`, `STRING`
2530 
2531#### Return type
2532 
2533`STRING`
2534 
2535#### Code samples
2536 
2537##### Integer to String Conversion
2538 
2539The function converts the integer `123` to the string `"123"`.
2540 
2541```
2542cast.as_string(123) = "123"
2543 
2544```
2545 
2546##### Float to String Conversion
2547 
2548The function converts the float `2.25` to the string `"2.25"`.
2549 
2550```
2551cast.as_string(2.25) = "2.25"
2552 
2553```
2554 
2555##### Bytes to String Conversion
2556 
2557The function converts the raw binary `b'01` to the string `"\x01"`.
2558 
2559```
2560cast.as_string(b'01, "") = "\x01"
2561 
2562```
2563 
2564##### Boolean to String Conversion
2565 
2566The function converts the boolean `true` to the string `"true"`.
2567 
2568```
2569cast.as_string(true, "") = "true"
2570 
2571```
2572 
2573##### Failed Conversion (Defaults to the Optionally Provided String)
2574 
2575The function defaults to the string `"casting error"` when the value provided is invalid.
2576 
2577```
2578cast.as_string(9223372036854775808, "casting error") = "casting error"
2579 
2580```
2581 
2582 
2583 
2584### fingerprint
2585 
2586Supported in:
2587 
2588[Rules](/chronicle/docs/detection/default-rules)
2589 
2590```
2591hash.fingerprint2011(byteOrString)
2592 
2593```
2594 
2595#### Description
2596 
2597This function calculates the `fingerprint2011` hash of an input byte sequence
2598or string. This function returns an unsigned `INT` value in the range `[2, 0xFFFFFFFFFFFFFFFF]`.
2599 
2600**Note:** This function shouldn't be used as a cryptographic secure hash.
2601 
2602#### Param data types
2603 
2604`BTYE`, `STRING`
2605 
2606#### Return type
2607 
2608`INT`
2609 
2610#### Code sample
2611 
2612```
2613id_fingerprint = hash.fingerprint2011("user123")
2614 
2615```
2616 
2617 
2618 
2619### group
2620 
2621Supported in:
2622 
2623[Search](/chronicle/docs/investigation/udm-search)
2624 
2625```
2626group(field1, field2, field3, ...)
2627 
2628```
2629 
2630#### Description
2631 
2632Group fields of a similar type into a placeholder variable.
2633 
2634In UDM search, [grouped
2635fields](/chronicle/docs/investigation/udm-search#search_grouped_fields) are used to search across multiple fields of a similar type. The group
2636function is similar to grouped fields except that it lets you select which fields you want
2637grouped together to trigger a detection. You can use the group function for gathering information about a specific entity (for example, a hostname, IP address, or userid) across different [Noun types](/chronicle/docs/reference/udm-field-list#noun).
2638 
2639**Note:** For search, you can use grouped fields in the events section, but not in
2640the match and outcome sections.
2641 
2642#### Code samples
2643 
2644**Example 1**
2645 
2646Group all the IP addresses together and provide a descending count of the most prevalent IP address in the time range scanned.
2647 
2648```
2649$ip = group(principal.ip, about.ip, target.ip)
2650$ip != ""
2651match:
2652 $ip
2653outcome:
2654 $count = count_distinct(metadata.id)
2655order:
2656 $count desc
2657 
2658```
2659 
2660 
2661 
2662### hash.sha256
2663 
2664Supported in:
2665 
2666[Rules](/chronicle/docs/detection/default-rules)
2667 
2668```
2669hash.sha256(string)
2670 
2671```
2672 
2673#### Description
2674 
2675Returns a SHA-256 hash of the input string.
2676 
2677#### Param data types
2678 
2679`STRING`
2680 
2681#### Return type
2682 
2683`STRING`
2684 
2685#### Code samples
2686 
2687##### Example 1
2688 
2689This example shows the SHA-256 hash when the input is a valid string.
2690 
2691```
2692hash.sha256("str") = "8c25cb3686462e9a86d2883c5688a22fe738b0bbc85f458d2d2b5f3f667c6d5a"
2693 
2694```
2695 
2696##### Example 2
2697 
2698This example shows the SHA-256 hash when the input is an empty string.
2699 
2700```
2701hash.sha256("") = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
2702 
2703```
2704 
2705 
2706 
2707### math.abs
2708 
2709Supported in:
2710 
2711[Rules](/chronicle/docs/detection/default-rules)
2712[Search](/chronicle/docs/investigation/udm-search)
2713 
2714```
2715math.abs(numericExpression)
2716 
2717```
2718 
2719#### Description
2720 
2721Returns the absolute value of an integer or float expression.
2722 
2723#### Param data types
2724 
2725`NUMBER`
2726 
2727#### Return type
2728 
2729`NUMBER`
2730 
2731#### Code samples
2732 
2733##### Example 1
2734 
2735This example returns True if the event was more than 5 minutes from the time
2736specified (in seconds from the Unix epoch), regardless of whether the event came
2737before or after the time specified. A call to `math.abs` cannot depend on
2738multiple variables or placeholders. For example, you cannot replace the
2739hardcoded time value of 1643687343 in the following example with
2740`$e2.metadata.event_timestamp.seconds`.
2741 
2742```
2743300 < math.abs($e1.metadata.event_timestamp.seconds - 1643687343)
2744 
2745```
2746 
2747 
2748 
2749### math.ceil
2750 
2751Supported in:
2752 
2753[Rules](/chronicle/docs/detection/default-rules)
2754[Search](/chronicle/docs/investigation/udm-search)
2755 
2756```
2757math.ceil(number)
2758 
2759```
2760 
2761#### Description
2762 
2763Returns the smallest integer that is not less than the given number (rounding up). Will return 0 if the input is null or too big to fit in an int64.
2764 
2765#### Param data types
2766 
2767`FLOAT`
2768 
2769#### Return type
2770 
2771`INT`
2772 
2773#### Code samples
2774 
2775This section contains examples of using `math.ceil`.
2776 
2777##### Example 1
2778 
2779This example returns the ceil of a whole number.
2780 
2781```
2782math.ceil(2.000000) = 2
2783 
2784```
2785 
2786##### Example 2
2787 
2788This example returns the ceil of a negative number.
2789 
2790```
2791math.ceil(0-1.200000) = -1
2792 
2793```
2794 
2795##### Example 3
2796 
2797This example returns 0 as the ceil of a number that is too big for a 64 bit integer.
2798 
2799```
2800math.ceil(184467440737095516160.0) = 0
2801 
2802```
2803 
2804 
2805 
2806### math.floor
2807 
2808Supported in:
2809 
2810[Rules](/chronicle/docs/detection/default-rules)
2811[Search](/chronicle/docs/investigation/udm-search)
2812 
2813```
2814math.floor(float_val)
2815 
2816```
2817 
2818#### Description
2819 
2820Returns the largest integer value that is not greater than the supplied value (rounding down). Returns 0 if the input is null or too large to fit into an int64.
2821 
2822#### Param data types
2823 
2824`FLOAT`
2825 
2826#### Return type
2827 
2828`INT`
2829 
2830#### Code samples
2831 
2832##### Example 1
2833 
2834This example shows a positive number case.
2835 
2836```
2837math.floor(1.234568) = 1
2838 
2839```
2840 
2841##### Example 2
2842 
2843This example shows a negative number case.
2844 
2845```
2846math.floor(0-1.234568) = -2
2847 
2848```
2849 
2850##### Example 3
2851 
2852This example shows a zero case.
2853 
2854```
2855math.floor(0.000000) = 0
2856 
2857```
2858 
2859 
2860 
2861### math.geo\_distance
2862 
2863Supported in:
2864 
2865[Rules](/chronicle/docs/detection/default-rules)
2866 
2867```
2868math.geo_distance(longitude1, latitude1, longitude2, latitude2))
2869 
2870```
2871 
2872#### Description
2873 
2874Returns the distance between two geographic locations (coordinates) in meters.
2875Returns -1 if the coordinates are invalid.
2876 
2877#### Parameter data types
2878 
2879`FLOAT`, `FLOAT`, `FLOAT`, `FLOAT`
2880 
2881#### Return type
2882 
2883`FLOAT`
2884 
2885#### Code samples
2886 
2887##### Example 1
2888 
2889The following example returns the distance when all parameters are valid
2890coordinates:
2891 
2892```
2893math.geo_distance(-122.020287, 37.407574, -122.021810, 37.407574) = 134.564318
2894 
2895```
2896 
2897##### Example 2
2898 
2899The following example returns the distance when one of the parameters is a
2900truncated coordinate:
2901 
2902```
2903math.geo_distance(-122.000000, 37.407574, -122.021810, 37.407574) = 1926.421905
2904 
2905```
2906 
2907##### Example 3
2908 
2909The following example returns `-1` when one of the parameters is an invalid
2910coordinate:
2911 
2912```
2913math.geo_distance(0-122.897680, 37.407574, 0-122.021810, 97.407574) = -1.000000
2914 
2915```
2916 
2917##### Example 4
2918 
2919The following example returns `0` when coordinates are the same:
2920 
2921```
2922math.geo_distance(-122.897680, 37.407574, -122.897680, 37.407574) = 0.000000
2923 
2924```
2925 
2926 
2927 
2928### math.is\_increasing
2929 
2930Supported in:
2931 
2932[Rules](/chronicle/docs/detection/default-rules)
2933[Search](/chronicle/docs/investigation/udm-search)
2934 
2935```
2936math.is_increasing(num1, num2, num3)
2937 
2938```
2939 
2940#### Description
2941 
2942Takes a list of numeric values (integers or doubles) and returns `True` if
2943the values are in ascending order, and `False` otherwise.
2944 
2945#### Param data types
2946 
2947`INT|FLOAT`, `INT|FLOAT`, `INT|FLOAT`
2948 
2949#### Return type
2950 
2951`BOOL`
2952 
2953#### Code samples
2954 
2955##### Example 1
2956 
2957This example includes timestamp-like values in seconds.
2958 
2959```
2960math.is_increasing(1716769112, 1716769113, 1716769114) = true
2961 
2962```
2963 
2964##### Example 2
2965 
2966This example includes one negative double, one zero INT64, and one positive INT64 values.
2967 
2968```
2969math.is_increasing(-1.200000, 0, 3) = true
2970 
2971```
2972 
2973##### Example 3
2974 
2975This example includes one negative double, one zero INT64, and one negative INT64 values.
2976 
2977```
2978math.is_increasing(0-1.200000, 0, 0-3) = false
2979 
2980```
2981 
2982##### Example 4
2983 
2984This example includes two negative doubles and one zero INT64 value.
2985 
2986```
2987math.is_increasing(0-1.200000, 0-1.50000, 0) = false
2988 
2989```
2990 
2991##### Example 5
2992 
2993This example includes one negative double and two values that are the same.
2994 
2995```
2996math.is_increasing(0-1.200000, 0, 0) = false
2997 
2998```
2999 
3000 
3001 
3002### math.log
3003 
3004Supported in:
3005 
3006[Rules](/chronicle/docs/detection/default-rules)
3007[Search](/chronicle/docs/investigation/udm-search)
3008 
3009```
3010math.log(numericExpression)
3011 
3012```
3013 
3014#### Description
3015 
3016Returns the natural log value of an integer or float expression.
3017 
3018#### Param data types
3019 
3020`NUMBER`
3021 
3022#### Return type
3023 
3024`NUMBER`
3025 
3026#### Code samples
3027 
3028##### Example 1
3029 
3030```
3031math.log($e1.network.sent_bytes) > 20
3032 
3033```
3034 
3035 
3036 
3037### math.pow
3038 
3039Supported in:
3040 
3041[Rules](/chronicle/docs/detection/default-rules)
3042[Search](/chronicle/docs/investigation/udm-search)
3043 
3044```
3045math.pow(base, exponent)
3046 
3047```
3048 
3049#### Description
3050 
3051Returns the value of the first arg raised to the power of the second arg. Returns 0 in case of overflow.
3052 
3053#### Param data types
3054 
3055base: `INT|FLOAT`
3056exponent: `INT|FLOAT`
3057 
3058#### Return type
3059 
3060`FLOAT`
3061 
3062#### Code samples
3063 
3064##### Example 1
3065 
3066This example shows an integer case.
3067 
3068```
3069math.pow(2, 2) // 4.00
3070 
3071```
3072 
3073##### Example 2
3074 
3075This example shows a fraction base case.
3076 
3077```
3078math.pow(2.200000, 3) // 10.648
3079 
3080```
3081 
3082##### Example 3
3083 
3084This example shows a fraction base and power case.
3085 
3086```
3087math.pow(2.200000, 1.200000) // 2.575771
3088 
3089```
3090 
3091##### Example 4
3092 
3093This example shows a negative power case.
3094 
3095```
3096math.pow(3, 0-3) // 0.037037
3097 
3098```
3099 
3100##### Example 5
3101 
3102This example shows a fraction power case.
3103 
3104```
3105math.pow(3, 0-1.200000) // 0.267581
3106 
3107```
3108 
3109##### Example 6
3110 
3111This example shows a negative base case.
3112 
3113```
3114math.pow(0-3, 0-3) // -0.037037
3115 
3116```
3117 
3118##### Example 7
3119 
3120This example shows a zero base case.
3121 
3122```
3123math.pow(0, 3) // 0
3124 
3125```
3126 
3127##### Example 8
3128 
3129This example shows a zero power case.
3130 
3131```
3132math.pow(9223372036854775807, 0) // 1
3133 
3134```
3135 
3136##### Example 9
3137 
3138This example shows a large base case.
3139 
3140```
3141math.pow(9223372036854775807, 1.200000) // 57262152889751593549824
3142 
3143```
3144 
3145 
3146 
3147### math.random
3148 
3149Supported in:
3150 
3151[Rules](/chronicle/docs/detection/default-rules)
3152[Search](/chronicle/docs/investigation/udm-search)
3153 
3154```
3155math.random()
3156 
3157```
3158 
3159#### Description
3160 
3161Generates a pseudo-random value of type DOUBLE in the range of `[0, 1)`, inclusive of 0 and exclusive of 1.
3162 
3163#### Return type
3164 
3165`FLOAT`
3166 
3167#### Code samples
3168 
3169The following example checks whether the random value is in the range `[0, 1)`.
3170`none
3171if(math.random() >= 0 and math.random() < 1) = true`
3172 
3173### math.round
3174 
3175Supported in:
3176 
3177[Search](/chronicle/docs/investigation/udm-search)
3178 
3179```
3180math.round(numericExpression, decimalPlaces)
3181 
3182```
3183 
3184#### Description
3185 
3186Returns a value rounded to the nearest integer or to the specified number of decimal places.
3187 
3188#### Param data types
3189 
3190`NUMBER`
3191 
3192#### Return type
3193 
3194`NUMBER`
3195 
3196#### Code samples
3197 
3198```
3199math.round(10.7) // returns 11
3200math.round(1.2567, 2) // returns 1.25
3201math.round(0-10.7) // returns -11
3202math.round(0-1.2) // returns -1
3203math.round(4) // returns 4, math.round(integer) returns the integer
3204 
3205```
3206 
3207 
3208 
3209### math.sqrt
3210 
3211Supported in:
3212 
3213[Rules](/chronicle/docs/detection/default-rules)
3214[Search](/chronicle/docs/investigation/udm-search)
3215 
3216```
3217math.sqrt(number)
3218 
3219```
3220 
3221#### Description
3222 
3223Returns the square root of the given number. Returns 0 in case of negative numbers.
3224 
3225#### Param data types
3226 
3227`INT|FLOAT`
3228 
3229#### Return type
3230 
3231`FLOAT`
3232 
3233#### Code samples
3234 
3235##### Example 1
3236 
3237This example returns the square root of an int argument.
3238 
3239```
3240math.sqrt(3) = 1.732051
3241 
3242```
3243 
3244##### Example 2
3245 
3246This example returns the square root of a negative int argument.
3247 
3248```
3249math.sqrt(-3) = 0.000000
3250 
3251```
3252 
3253##### Example 3
3254 
3255This example returns the square root of zero argument.
3256 
3257```
3258math.sqrt(0) = 0.000000
3259 
3260```
3261 
3262##### Example 4
3263 
3264This example returns the square root of a float argument.
3265 
3266```
3267math.sqrt(9.223372) = 3.037000
3268 
3269```
3270 
3271##### Example 5
3272 
3273This example returns the square root of a negative float argument.
3274 
3275```
3276math.sqrt(0-1.200000) = 0.000000
3277 
3278```
3279 
3280 
3281 
3282### metrics
3283 
3284Supported in:
3285 
3286[Rules](/chronicle/docs/detection/default-rules)
3287 
3288Metrics functions can aggregate large amounts of historical data. You can use
3289this in your rule using `metrics.functionName()` in the outcome
3290section.
3291 
3292For more information, see [YARA-L Metrics](/chronicle/docs/detection/metrics-functions).
3293 
3294### net.ip\_in\_range\_cidr
3295 
3296Supported in:
3297 
3298[Rules](/chronicle/docs/detection/default-rules)
3299[Search](/chronicle/docs/investigation/udm-search)
3300 
3301```
3302net.ip_in_range_cidr(ipAddress, subnetworkRange)
3303 
3304```
3305 
3306#### Description
3307 
3308Returns `true` when the given IP address is within the specified subnetwork.
3309 
3310You can use YARA-L to search for UDM events across all of the IP addresses
3311within a subnetwork using the `net.ip_in_range_cidr()` statement.
3312Both IPv4 and IPv6 are supported.
3313 
3314To search across a range of IP addresses, specify an IP UDM field and a CIDR
3315range. YARA-L can handle both singular and repeating IP address fields.
3316 
3317To search across a range of IP addresses, specify an `ip` UDM field and a Classless Inter-Domain Routing (CIDR) range. YARA-L can handle both singular and repeating IP address fields.
3318 
3319#### Param data types
3320 
3321`STRING`, `STRING`
3322 
3323#### Return type
3324 
3325`BOOL`
3326 
3327#### Code samples
3328 
3329##### Example 1
3330 
3331IPv4 example:
3332 
3333```
3334net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/24")
3335 
3336```
3337 
3338##### Example 2
3339 
3340IPv6 example:
3341 
3342```
3343net.ip_in_range_cidr($e.network.dhcp.yiaddr, "2001:db8::/32")
3344 
3345```
3346 
3347For an example rule using the `net.ip_in_range_cidr()`statement, see the example rule in [Single Event within Range of IP Addresses](/chronicle/docs/detection/yara-l-2-0-overview#single_event_within_range_of_ip_addresses).)
3348 
3349### re.regex
3350 
3351Supported in:
3352 
3353[Rules](/chronicle/docs/detection/default-rules)
3354[Search](/chronicle/docs/investigation/udm-search)
3355 
3356You can define regular expression matching in YARA-L 2.0 using either of the following syntax:
3357 
3358* Using YARA-L syntax — Related to events.
3359 The following is a generic representation of this syntax:
3360 
3361```
3362 $e.field = /regex/
3363 
3364```
3365* Using YARA-L syntax — As a function taking in the following parameters:
3366 
3367 + Field the regular expression is applied to.
3368 + Regular expression specified as a string.
3369 
3370 The following is a generic representation of this syntax:
3371 
3372```
3373 re.regex($e.field, `regex`)
3374 
3375```
3376 
3377#### Description
3378 
3379This function returns `true` if the string contains a substring that matches the regular expression provided. It is unnecessary to add `.*` to the beginning or at the end of the regular expression.
3380 
3381##### Notes
3382 
3383* To match the exact string or only a prefix or suffix, include the `^`
3384 (starting) and `$` (ending) anchor characters in the regular expression.
3385 For example, `/^full$/` matches `"full"` exactly, while `/full/` could match
3386 `"fullest"`, `"lawfull"`, and `"joyfully"`.
3387* If the UDM field includes newline characters, the `regexp` only matches the
3388 first line of the UDM field. To enforce full UDM field matching, add a `(?s)` to
3389 the regular expression. For example, replace `/.*allUDM.*/` with
3390 `/(?s).*allUDM.*/`.
3391* You can use the `nocase` modifier after strings to indicate that the search
3392 should ignore capitalization.
3393 
3394#### Param data types
3395 
3396`STRING`, `STRING`
3397 
3398#### Param expression types
3399 
3400`ANY`, `ANY`
3401 
3402#### Return type
3403 
3404`BOOL`
3405 
3406#### Code samples
3407 
3408##### Example 1
3409 
3410```
3411// Equivalent to $e.principal.hostname = /google/
3412re.regex($e.principal.hostname, "google")
3413 
3414```
3415 
3416 
3417 
3418### re.capture
3419 
3420Supported in:
3421 
3422[Rules](/chronicle/docs/detection/default-rules)
3423[Search](/chronicle/docs/investigation/udm-search)
3424 
3425```
3426re.capture(stringText, regex)
3427 
3428```
3429 
3430#### Description
3431 
3432Captures (extracts) data from a string using the regular expression pattern
3433provided in the argument.
3434 
3435This function takes two arguments:
3436 
3437* `stringText`: the original string to search.
3438* `regex`: the regular expression indicating the pattern to search for.
3439 
3440The regular expression can contain 0 or 1 capture groups in parentheses. If the
3441regular expression contains 0 capture groups, the function returns the first
3442entire matching substring. If the regular expression contains 1 capture group,
3443it returns the first matching substring for the capture group. Defining two or
3444more capture groups returns a compiler error.
3445 
3446#### Param data types
3447 
3448`STRING`, `STRING`
3449 
3450#### Return type
3451 
3452`STRING`
3453 
3454#### Code samples
3455 
3456##### Example 1
3457 
3458In this example, if `$e.principal.hostname` contains "aaa1bbaa2" the following would be true, because the function
3459returns the first instance. This example has no capture groups.
3460 
3461```
3462"aaa1" = re.capture($e.principal.hostname, "a+[1-9]")
3463 
3464```
3465 
3466##### Example 2
3467 
3468This example captures everything after the @ symbol in an email. If the
3469`$e.network.email.from` field is `test@google.com`, the example returns
3470`google.com`. The following example contains one capture group.
3471 
3472```
3473"google.com" = re.capture($e.network.email.from , "@(.*)")
3474 
3475```
3476 
3477##### Example 3
3478 
3479If the regular expression does not match any substring in the text, the
3480function returns an empty string. You can omit events where no match occurs
3481by excluding the empty string, which is especially important when you are
3482using `re.capture()` with an inequality:
3483 
3484```
3485// Exclude the empty string to omit events where no match occurs.
3486"" != re.capture($e.network.email.from , "@(.*)")
3487 
3488// Exclude a specific string with an inequality.
3489"google.com" != re.capture($e.network.email.from , "@(.*)")
3490 
3491```
3492 
3493 
3494 
3495### re.replace
3496 
3497Supported in:
3498 
3499[Rules](/chronicle/docs/detection/default-rules)
3500[Search](/chronicle/docs/investigation/udm-search)
3501 
3502```
3503re.replace(stringText, replaceRegex, replacementText)
3504 
3505```
3506 
3507#### Description
3508 
3509Performs a regular expression replacement.
3510 
3511This function takes three arguments:
3512 
3513* `stringText`: the original string.
3514* `replaceRegex`: the regular expression indicating the pattern to search for.
3515* `replacementText`: The text to insert into each match.
3516 
3517Returns a new string derived from the original `stringText`, where all
3518substrings that match the pattern in `replaceRegex` are replaced with the value in
3519`replacementText`. You can use backslash-escaped digits (`\1` to `\9`) within
3520`replacementText` to insert text matching the corresponding parenthesized group
3521in the `replaceRegex` pattern. Use `\0` to refer to the entire matching text.
3522 
3523The function replaces non-overlapping matches and will prioritize replacing the
3524first occurrence found. For example, `re.replace("banana", "ana", "111")`
3525returns the string "b111na".
3526 
3527#### Param data types
3528 
3529`STRING`, `STRING`, `STRING`
3530 
3531#### Return type
3532 
3533`STRING`
3534 
3535#### Code samples
3536 
3537##### Example 1
3538 
3539This example captures everything after the `@` symbol in an email, replaces `com`
3540with `org`, and then returns the result. Notice the use of nested functions.
3541 
3542```
3543"email@google.org" = re.replace($e.network.email.from, "com", "org")
3544 
3545```
3546 
3547##### Example 2
3548 
3549This example uses backslash-escaped digits in the `replacementText` argument to
3550reference matches to the `replaceRegex` pattern.
3551 
3552```
3553"test1.com.google" = re.replace(
3554 $e.principal.hostname, // holds "test1.test2.google.com"
3555 "test2\.([a-z]*)\.([a-z]*)",
3556 "\\2.\\1" // \\1 holds "google", \\2 holds "com"
3557 )
3558 
3559```
3560 
3561##### Example 3
3562 
3563Note the following cases when dealing with empty strings and `re.replace()`:
3564 
3565Using empty string as `replaceRegex`:
3566 
3567```
3568// In the function call below, if $e.principal.hostname contains "name",
3569// the result is: 1n1a1m1e1, because an empty string is found next to
3570// every character in `stringText`.
3571re.replace($e.principal.hostname, "", "1")
3572 
3573```
3574 
3575To replace an empty string, you can use `"^$"` as `replaceRegex`:
3576 
3577```
3578// In the function call below, if $e.principal.hostname contains the empty
3579// string, "", the result is: "none".
3580re.replace($e.principal.hostname, "^$", "none")
3581 
3582```
3583 
3584 
3585 
3586### sample\_rate
3587 
3588Supported in:
3589 
3590[Rules](/chronicle/docs/detection/default-rules)
3591 
3592```
3593optimization.sample_rate(byteOrString, rateNumerator, rateDenominator)
3594 
3595```
3596 
3597#### Description
3598 
3599This function determines whether to include an event based on a deterministic
3600sampling strategy. This function returns:
3601 
3602* `true` for a fraction of input values, equivalent to (`rateNumerator` / `rateDenominator`),
3603 indicating that the event should be included in the sample.
3604* `false` indicating that the event shouldn't be included in the sample.
3605 
3606This function is useful for optimization scenarios where you want to process
3607only a subset of events. Equivalent to:
3608 
3609```
3610hash.fingerprint2011(byteOrString) % rateDenominator < rateNumerator
3611 
3612```
3613 
3614#### Param data types
3615 
3616* byteOrString: Expression that evaluates to either a `BYTE` or `STRING`.
3617* rateNumerator: 'INT'
3618* rateDenominator: 'INT'
3619 
3620#### Return type
3621 
3622`BOOL`
3623 
3624#### Code sample
3625 
3626```
3627events:
3628 $e.metadata.event_type = "NETWORK_CONNECTION"
3629 $asset_id = $e.principal.asset.asset_id
3630 optimization.sample_rate($e.metadata.id, 1, 5) // Only 1 out of every 5 events
3631 
3632 match:
3633 $asset_id over 1h
3634 
3635 outcome:
3636 $event_count = count_distinct($e.metadata.id)
3637 // estimate the usage by multiplying by the inverse of the sample rate
3638 $usage_past_hour = sum(5.0 * $e.network.sent_bytes)
3639 
3640 condition:
3641 // Requiring a certain number of events after sampling avoids bias (e.g. a
3642 // device with just 1 connection will still show up 20% of the time and
3643 // if we multiply that traffic by 5, we'll get an incorrect estimate)
3644 $e and ($usage_past_hour > 1000000000) and $event_count >= 100
3645 
3646```
3647 
3648 
3649 
3650### strings.base64\_decode
3651 
3652Supported in:
3653 
3654[Rules](/chronicle/docs/detection/default-rules)
3655[Search](/chronicle/docs/investigation/udm-search)
3656 
3657```
3658strings.base64_decode(encodedString)
3659 
3660```
3661 
3662#### Description
3663 
3664Returns a string containing the base64 decoded version of the encoded string.
3665 
3666This function takes one base64 encoded string as an argument. If `encodedString`
3667is not a valid base64 encoded string, the function returns `encodedString` unchanged.
3668 
3669#### Param data types
3670 
3671`STRING`
3672 
3673#### Return type
3674 
3675`STRING`
3676 
3677#### Code samples
3678 
3679##### Example 1
3680 
3681```
3682"test" = strings.base64_decode($e.principal.domain.name)
3683 
3684```
3685 
3686 
3687 
3688### strings.coalesce
3689 
3690Supported in:
3691 
3692[Rules](/chronicle/docs/detection/default-rules)
3693[Search](/chronicle/docs/investigation/udm-search)
3694 
3695```
3696strings.coalesce(a, b, c, ...)
3697 
3698```
3699 
3700#### Description
3701 
3702This function takes an unlimited number of arguments and returns the value of the first expression that does not evaluate to an empty string (for example, "non-zero value"). If all arguments evaluate to an empty string, the function call returns an empty string.
3703 
3704The arguments can be literals, event fields, or function calls. All arguments must be of `STRING` type. If any arguments are event fields, the attributes must be from the same event.
3705 
3706#### Param data types
3707 
3708`STRING`
3709 
3710#### Return type
3711 
3712`STRING`
3713 
3714#### Code samples
3715 
3716##### Example 1
3717 
3718The following example includes string variables as arguments. The condition
3719evaluates to true when (1) `$e.network.email.from` is `suspicious@gmail.com` or
3720(2) `$e.network.email.from` is empty and `$e.network.email.to` is
3721`suspicious@gmail.com`.
3722 
3723```
3724"suspicious@gmail.com" = strings.coalesce($e.network.email.from, $e.network.email.to)
3725 
3726```
3727 
3728##### Example 2
3729 
3730The following example calls the `coalesce` function with more than two
3731arguments. This condition compares the first non-null IP address from event `$e`
3732against values in the reference list `ip_watchlist`. The order that the
3733arguments are coalesced in this call is the same as the order they are
3734enumerated in the rule condition:
3735 
37361. `$e.principal.ip` is evaluated first.
37372. `$e.src.ip` is evaluated next.
37383. `$e.target.ip` is evaluated next.
37394. Finally, the string "No IP" is returned as a default value if the previous `ip`
3740 fields are unset.
3741 
3742```
3743strings.coalesce($e.principal.ip, $e.src.ip, $e.target.ip, "No IP") in %ip_watchlist
3744 
3745```
3746 
3747##### Example 3
3748 
3749The following example attempts to coalesce `principal.hostname` from event
3750`$e1` and event `$e2`. It will return a compiler error because the arguments are
3751different event variables.
3752 
3753```
3754// returns a compiler error
3755"test" = strings.coalesce($e1.principal.hostname, $e2.principal.hostname)
3756 
3757```
3758 
3759 
3760 
3761### strings.concat
3762 
3763Supported in:
3764 
3765[Rules](/chronicle/docs/detection/default-rules)
3766[Search](/chronicle/docs/investigation/udm-search)
3767 
3768```
3769strings.concat(a, b, c, ...)
3770 
3771```
3772 
3773#### Description
3774 
3775Returns the concatenation of an unlimited number of items, each of which can be
3776a string, integer, or float.
3777 
3778If any arguments are event fields, the attributes must be from the same event.
3779 
3780#### Param data types
3781 
3782`STRING`, `FLOAT`, `INT`
3783 
3784#### Return type
3785 
3786`STRING`
3787 
3788#### Code samples
3789 
3790##### Example 1
3791 
3792The following example includes a string variable and integer variable as
3793arguments. Both `principal.hostname` and `principal.port` are from the same
3794event, `$e`, and are concatenated to return a string.
3795 
3796```
3797"google:80" = strings.concat($e.principal.hostname, ":", $e.principal.port)
3798 
3799```
3800 
3801##### Example 2
3802 
3803The following example includes a string variable and string literal as arguments.
3804 
3805```
3806"google-test" = strings.concat($e.principal.hostname, "-test") // Matches the event when $e.principal.hostname = "google"
3807 
3808```
3809 
3810##### Example 3
3811 
3812The following example includes a string variable and float literal as arguments.
3813When represented as strings, floats that are whole numbers are formatted without
3814the decimal point (for example, 1.0 is represented as "1"). Additionally,
3815floats that exceed sixteen decimal digits are truncated to the sixteenth decimal
3816place.
3817 
3818```
3819"google2.5" = strings.concat($e.principal.hostname, 2.5)
3820 
3821```
3822 
3823##### Example 4
3824 
3825The following example includes a string variable, string literal,
3826integer variable, and float literal as arguments. All variables are from the
3827same event, `$e`, and are concatenated with the literals to return a string.
3828 
3829```
3830"google-test802.5" = strings.concat($e.principal.hostname, "-test", $e.principal.port, 2.5)
3831 
3832```
3833 
3834##### Example 5
3835 
3836The following example attempts to concatenate principal.port from event `$e1`,
3837with `principal.hostname` from event `$e2`. It will return a compiler error
3838because the arguments are different event variables.
3839 
3840```
3841// Will not compile
3842"test" = strings.concat($e1.principal.port, $e2.principal.hostname)
3843 
3844```
3845 
3846 
3847 
3848### strings.contains
3849 
3850Supported in:
3851 
3852[Rules](/chronicle/docs/detection/default-rules)
3853[Search](/chronicle/docs/investigation/udm-search)
3854 
3855```
3856strings.contains( str, substr )
3857 
3858```
3859 
3860#### Description
3861 
3862Returns true if a given string contains the specified substring. Otherwise it returns false.
3863 
3864#### Param data types
3865 
3866`STRING`, `STRING`
3867 
3868#### Return type
3869 
3870`BOOL`
3871 
3872#### Code samples
3873 
3874##### Example 1
3875 
3876This example returns true because the string has a substring "is".
3877 
3878```
3879strings.contains("thisisastring", "is") = true
3880 
3881```
3882 
3883##### Example 2
3884 
3885This example returns false because the string does not have substring "that".
3886 
3887```
3888strings.contains("thisisastring", "that") = false
3889 
3890```
3891 
3892 
3893 
3894### strings.count\_substrings
3895 
3896Supported in:
3897 
3898[Rules](/chronicle/docs/detection/default-rules)
3899[Search](/chronicle/docs/investigation/udm-search)
3900 
3901```
3902strings.count_substrings(string_to_search_in, substring_to_count)
3903 
3904```
3905 
3906#### Description
3907 
3908When given a string and a substring, returns an int64 of the count of non-overlapping occurrences of the substring within the string.
3909 
3910#### Param data types
3911 
3912`STRING`, `STRING`
3913 
3914#### Return type
3915 
3916`INT`
3917 
3918#### Code samples
3919 
3920This section contains examples that calculate the number of times a substring appears in a given string.
3921 
3922##### Example 1
3923 
3924This example uses a non-null string and a non-null single substring character.
3925 
3926```
3927strings.count_substrings("this`string`has`four`backticks", "`") = 4
3928 
3929```
3930 
3931##### Example 2
3932 
3933This example uses a non-null string and a non-null substring greater than one character.
3934 
3935```
3936strings.count_substrings("str", "str") = 1
3937 
3938```
3939 
3940##### Example 3
3941 
3942This example uses a non-null string and an empty substring.
3943 
3944```
3945strings.count_substrings("str", "") = 0
3946 
3947```
3948 
3949##### Example 4
3950 
3951This example uses an empty string and a non-null substring greater than one character.
3952 
3953```
3954strings.count_substrings("", "str") = 0
3955 
3956```
3957 
3958##### Example 5
3959 
3960This example uses an empty string and an empty substring.
3961 
3962```
3963strings.count_substrings("", "") = 0
3964 
3965```
3966 
3967##### Example 6
3968 
3969This example uses a non-null string and a non-null substring that is greater than one character and greater than one occurrence.
3970 
3971```
3972strings.count_substrings("fooABAbarABAbazABA", "AB") = 3
3973 
3974```
3975 
3976##### Example 7
3977 
3978This example uses a non-null string and a non-null substring that is greater than one character and greater than one occurrence. It highlights the limitation with overlapping substring occurrences
3979 
3980```
3981strings.count_substrings("ABABABA", "ABA") = 2
3982 
3983```
3984 
3985 
3986 
3987### strings.extract\_domain
3988 
3989Supported in:
3990 
3991[Rules](/chronicle/docs/detection/default-rules)
3992[Search](/chronicle/docs/investigation/udm-search)
3993 
3994```
3995strings.extract_domain(url_string)
3996 
3997```
3998 
3999#### Description
4000 
4001Extracts the domain from a string.
4002 
4003**Note:** The function does not perform Unicode normalization.**Note:** The public suffix data at publicsuffix.org also contains private domains. This function does not treat a private domain as a public suffix. For example, if us.com is a private domain in the public suffix data, ("foo.us.com") returns us.com (the public suffix com plus the preceding label us) rather than foo.us.com (the private domain us.com plus the preceding label foo).**Note:** The public suffix data might change over time. Consequently, input that produces default empty value now may produce a non-empty value in the future.
4004 
4005#### Param data types
4006 
4007`STRING`
4008 
4009#### Return type
4010 
4011`STRING`
4012 
4013#### Code samples
4014 
4015##### Example 1
4016 
4017This example shows an empty string
4018 
4019```
4020strings.extract_domain("") = ""
4021 
4022```
4023 
4024##### Example 2
4025 
4026random string, not a URL
4027 
4028```
4029strings.extract_domain("1234") = ""
4030 
4031```
4032 
4033##### Example 3
4034 
4035multiple backslaches
4036 
4037```
4038strings.extract_domain("\\\\") = ""
4039 
4040```
4041 
4042##### Example 4
4043 
4044non-alphabet characters handled gracefully
4045 
4046```
4047strings.extract_domain("http://例子.卷筒纸.中国") = "卷筒纸.中国"
4048 
4049```
4050 
4051##### Example 5
4052 
4053handling URIs
4054 
4055```
4056strings.extract_domain("mailto:?to=&subject=&body=") = ""
4057 
4058```
4059 
4060##### Example 6
4061 
4062multiple characters before actual URL
4063 
4064```
4065strings.extract_domain(" \t !$5*^)&dahgsdfs;http://www.google.com") = "google.com"
4066 
4067```
4068 
4069##### Example 7
4070 
4071special characters in URI `#`
4072 
4073```
4074strings.extract_domain("test#@google.com") = ""
4075 
4076```
4077 
4078##### Example 8
4079 
4080special characters in URL `#`
4081 
4082```
4083strings.extract_domain("https://test#@google.com") = ""
4084 
4085```
4086 
4087##### Example 9
4088 
4089positive test case
4090 
4091```
4092strings.extract_domain("https://google.co.in") = "google.co.in"
4093 
4094```
4095 
4096 
4097 
4098### strings.extract\_hostname
4099 
4100Supported in:
4101 
4102[Rules](/chronicle/docs/detection/default-rules)
4103[Search](/chronicle/docs/investigation/udm-search)
4104 
4105```
4106strings.extract_hostname(string)
4107 
4108```
4109 
4110#### Description
4111 
4112Extracts the hostname from a string. This function is case sensitive.
4113 
4114#### Param data types
4115 
4116`STRING`
4117 
4118#### Return type
4119 
4120`STRING`
4121 
4122#### Code samples
4123 
4124##### Example 1
4125 
4126This example returns an empty string.
4127 
4128```
4129strings.extract_hostname("") = ""
4130 
4131```
4132 
4133##### Example 2
4134 
4135random string, not a URL
4136 
4137```
4138strings.extract_hostname("1234") = "1234"
4139 
4140```
4141 
4142##### Example 3
4143 
4144multiple backslashes
4145 
4146```
4147strings.extract_hostname("\\\\") = ""
4148 
4149```
4150 
4151##### Example 4
4152 
4153non-English characters handled gracefully
4154 
4155```
4156strings.extract_hostname("http://例子.卷筒纸.中国") = "例子.卷筒纸.中国"
4157 
4158```
4159 
4160##### Example 5
4161 
4162handling URIs
4163 
4164```
4165strings.extract_hostname("mailto:?to=&subject=&body=") = "mailto"
4166 
4167```
4168 
4169##### Example 6
4170 
4171multiple characters before actual URL
4172 
4173```
4174strings.extract_hostname(" \t !$5*^)&dahgsdfs;http://www.google.com") = "www.google.com"
4175 
4176```
4177 
4178##### Example 7
4179 
4180special characters in URI `#`
4181 
4182```
4183strings.extract_hostname("test#@google.com") = "test"
4184 
4185```
4186 
4187##### Example 8
4188 
4189special characters in URL `#`
4190 
4191```
4192strings.extract_hostname("https://test#@google.com") = "test"
4193 
4194```
4195 
4196 
4197 
4198### strings.from\_base64
4199 
4200Supported in:
4201 
4202[Rules](/chronicle/docs/detection/default-rules)
4203[Search](/chronicle/docs/investigation/udm-search)
4204 
4205```
4206strings.from_base64(base64_encoded_string)
4207 
4208```
4209 
4210#### Description
4211 
4212Function converts a base64 encoded `STRING` value to a raw binary `BYTES` value. Function calls with values that cannot be casted return an empty `BYTES` by default.
4213 
4214#### Param data types
4215 
4216`STRING`
4217 
4218#### Return type
4219 
4220`BYTES`
4221 
4222#### Code samples
4223 
4224##### Base64 Encoded String to Bytes Conversion
4225 
4226The function converts a base64 encoded string to its raw binary bytes representation.
4227 
4228```
4229strings.from_base64("AAAAAG+OxVhtAm+d2sVuny/hW4oAAAAAAQAAAM0AAAA=") = b'000000006f8ec5586d026f9ddac56e9f2fe15b8a0000000001000000cd000000
4230 
4231```
4232 
4233##### Failed Conversion (Defaults to Empty Bytes)
4234 
4235The function defaults to empty bytes if the provided value in invalid.
4236 
4237```
4238strings.from_base64("invalid-value") = b'
4239 
4240```
4241 
4242 
4243 
4244### strings.from\_hex
4245 
4246Supported in:
4247 
4248[Rules](/chronicle/docs/detection/default-rules)
4249[Search](/chronicle/docs/investigation/udm-search)
4250 
4251```
4252strings.from_hex(hex_string)
4253 
4254```
4255 
4256#### Description
4257 
4258Returns the bytes associated with the given hex string.
4259 
4260#### Param data types
4261 
4262`STRING`
4263 
4264#### Return type
4265 
4266`BYTES`
4267 
4268#### Code samples
4269 
4270Get bytes associated with a given hex string.
4271 
4272##### Example 1
4273 
4274This example shows non-hex character conversions.
4275 
4276```
4277strings.from_hex("str") // returns empty bytes
4278 
4279```
4280 
4281##### Example 2
4282 
4283This example shows input with empty string.
4284 
4285```
4286strings.from_hex("") // returns empty bytes
4287 
4288```
4289 
4290##### Example 3
4291 
4292This example shows hex string conversion.
4293 
4294```
4295strings.from_hex("1234") // returns 1234 bytes
4296 
4297```
4298 
4299##### Example 4
4300 
4301This example shows non-ASCII characters conversion.
4302 
4303```
4304strings.from_hex("筒纸.中国") // returns empty bytes
4305 
4306```
4307 
4308 
4309 
4310### strings.length
4311 
4312Supported in:
4313 
4314[Rules](/chronicle/docs/detection/default-rules)
4315[Search](/chronicle/docs/investigation/udm-search)
4316 
4317```
4318strings.length(string_value)
4319 
4320```
4321 
4322#### Description
4323 
4324Returns the number of characters in the input string.
4325 
4326#### Param data types
4327 
4328`STRING`
4329 
4330#### Return type
4331 
4332`INT`
4333 
4334#### Code samples
4335 
4336##### Example 1
4337 
4338The following is an example with a string test.
4339 
4340```
4341strings.length("str") = 3
4342 
4343```
4344 
4345##### Example 2
4346 
4347The following is an example with an empty string as input.
4348 
4349```
4350strings.length("") = 0
4351 
4352```
4353 
4354##### Example 3
4355 
4356The following is an example with a special char string.
4357 
4358```
4359strings.length("!@#$%^&*()-_") = 12
4360 
4361```
4362 
4363##### Example 4
4364 
4365The following is an example with a string with spaces.
4366 
4367```
4368strings.length("This is a test string") = 21
4369 
4370```
4371 
4372 
4373 
4374### strings.ltrim
4375 
4376Supported in:
4377 
4378[Rules](/chronicle/docs/detection/default-rules)
4379[Search](/chronicle/docs/investigation/udm-search)
4380 
4381```
4382strings.ltrim(string_to_trim, cutset)
4383 
4384```
4385 
4386#### Description
4387 
4388Trims leading white spaces from a given string. This function removes leading characters present in that cutset.
4389 
4390#### Param data types
4391 
4392`STRING`, `STRING`
4393 
4394#### Return type
4395 
4396`STRING`
4397 
4398#### Code samples
4399 
4400The following are example use cases.
4401 
4402##### Example 1
4403 
4404This example uses the same first and second argument.
4405 
4406```
4407strings.ltrim("str", "str") = ""
4408 
4409```
4410 
4411##### Example 2
4412 
4413This example uses an empty string as the second argument.
4414 
4415```
4416strings.ltrim("str", "") = "str"
4417 
4418```
4419 
4420##### Example 3
4421 
4422This example uses an empty string as the first argument, and a string as the second argument.
4423 
4424```
4425strings.ltrim("", "str") = ""
4426 
4427```
4428 
4429##### Example 4
4430 
4431This example uses strings that contain white spaces, and a string as the second argument.
4432 
4433```
4434strings.ltrim("a aastraa aa ", " a") = "straa aa "
4435 
4436```
4437 
4438 
4439 
4440### strings.reverse
4441 
4442Supported in:
4443 
4444[Rules](/chronicle/docs/detection/default-rules)
4445[Search](/chronicle/docs/investigation/udm-search)
4446 
4447```
4448strings.reverse(STRING)
4449 
4450```
4451 
4452#### Description
4453 
4454Returns a string that is the reverse of the input string.
4455 
4456#### Param data types
4457 
4458`STRING`
4459 
4460#### Return type
4461 
4462`STRING`
4463 
4464#### Code samples
4465 
4466##### Example 1
4467 
4468The following example passes a short string.
4469 
4470```
4471strings.reverse("str") = "rts" // The function returns 'rts'.
4472 
4473```
4474 
4475##### Example 2
4476 
4477The following example passes an empty string.
4478 
4479```
4480strings.reverse("") = ""
4481 
4482```
4483 
4484##### Example 3
4485 
4486The following example passes a palindrome.
4487 
4488```
4489strings.reverse("tacocat") = "tacocat"
4490 
4491```
4492 
4493 
4494 
4495### strings.rtrim
4496 
4497Supported in:
4498 
4499[Rules](/chronicle/docs/detection/default-rules)
4500[Search](/chronicle/docs/investigation/udm-search)
4501 
4502```
4503strings.rtrim(string_to_trim, cutset)
4504 
4505```
4506 
4507#### Description
4508 
4509Trims trailing white spaces from a given string. Removes trailing characters that are present in that cutset.
4510 
4511#### Param data types
4512 
4513`STRING`, `STRING`
4514 
4515#### Return type
4516 
4517`STRING`
4518 
4519#### Code samples
4520 
4521The following are example use cases.
4522 
4523##### Example 1
4524 
4525The following example passes the same string as the first and second argument.
4526 
4527```
4528strings.rtrim("str", "str") = ""
4529 
4530```
4531 
4532##### Example 2
4533 
4534The following example passes an empty string as the second argument.
4535 
4536```
4537strings.rtrim("str", "") = "str"
4538 
4539```
4540 
4541##### Example 3
4542 
4543The following example passes an empty string as the first argument and a non-empty string as the second argument.
4544 
4545```
4546strings.rtrim("", "str") = ""
4547 
4548```
4549 
4550##### Example 4
4551 
4552The following example passes a string containing white spaces as the first argument and a non-empty string as the second argument.
4553 
4554```
4555strings.rtrim("a aastraa aa ", " a") = "a aasstr"
4556 
4557```
4558 
4559 
4560 
4561### strings.to\_lower
4562 
4563Supported in:
4564 
4565[Rules](/chronicle/docs/detection/default-rules)
4566[Search](/chronicle/docs/investigation/udm-search)
4567 
4568```
4569strings.to_lower(stringText)
4570 
4571```
4572 
4573#### Description
4574 
4575This function takes an input string and returns a string after changing all
4576characters to lowercase
4577 
4578#### Param data types
4579 
4580`STRING`
4581 
4582#### Return type
4583 
4584`STRING`
4585 
4586#### Code samples
4587 
4588##### Example 1
4589 
4590The following example returns `true`.
4591 
4592```
4593"test@google.com" = strings.to_lower($e.network.email.to)
4594 
4595```
4596 
4597 
4598 
4599### strings.to\_upper
4600 
4601Supported in:
4602 
4603[Rules](/chronicle/docs/detection/default-rules)
4604[Search](/chronicle/docs/investigation/udm-search)
4605 
4606```
4607strings.to_upper(string_val)
4608 
4609```
4610 
4611#### Description
4612 
4613Returns the original string with all alphabetic characters in uppercase.
4614 
4615#### Param data types
4616 
4617`STRING`
4618 
4619#### Return type
4620 
4621`STRING`
4622 
4623#### Code samples
4624 
4625##### Example 1
4626 
4627The following example returns the supplied argument in uppercase.
4628 
4629```
4630strings.to_upper("example") = "EXAMPLE"
4631 
4632```
4633 
4634 
4635 
4636### strings.trim
4637 
4638Supported in:
4639 
4640[Rules](/chronicle/docs/detection/default-rules)
4641[Search](/chronicle/docs/investigation/udm-search)
4642 
4643```
4644strings.trim(string_to_trim, cutset)
4645 
4646```
4647 
4648#### Description
4649 
4650Trims leading and trailing white spaces from a given string. Also, remove unwanted characters (specified by the cutset argument) from the input string.
4651 
4652#### Param data types
4653 
4654`STRING`, `STRING`
4655 
4656#### Return type
4657 
4658`STRING`
4659 
4660#### Code samples
4661 
4662The following are example use cases.
4663 
4664##### Example 1
4665 
4666In the following example, the same string is passed as the input string and the cutset, which results in an empty string.
4667 
4668```
4669strings.trim("str", "str") // ""
4670 
4671```
4672 
4673##### Example 2
4674 
4675In the following example, an empty string is passed as the cutset, which results in the original string str because there are no characters specified in the cutset to remove.
4676 
4677```
4678strings.trim("str", "") = "str"
4679 
4680```
4681 
4682##### Example 3
4683 
4684In the following example, the function yields an empty string because the input string is already empty and there are no characters to remove.
4685 
4686```
4687strings.trim("", "str") = ""
4688 
4689```
4690 
4691##### Example 4
4692 
4693In the following example, the function yields str because the trim function removes the following:
4694 
4695* trailing whitespace in "a aastraa aa "
4696* the characters specified in the cutset (space, a)
4697 
4698```
4699strings.trim("a aastraa aa ", " a") = "str"
4700 
4701```
4702 
4703 
4704 
4705### strings.url\_decode
4706 
4707Supported in:
4708 
4709[Rules](/chronicle/docs/detection/default-rules)
4710[Search](/chronicle/docs/investigation/udm-search)
4711 
4712```
4713strings.url_decode(url_string)
4714 
4715```
4716 
4717#### Description
4718 
4719Given a URL string, decode the escape characters and handle UTF-8 characters that have been encoded. Returns empty string if decoding fails.
4720 
4721#### Param data types
4722 
4723`STRING`
4724 
4725#### Return type
4726 
4727`STRING`
4728 
4729#### Code samples
4730 
4731##### Example 1
4732 
4733This example shows a positive test case.
4734 
4735```
4736strings.url_decode("three%20nine%20four") = "three nine four"
4737 
4738```
4739 
4740##### Example 2
4741 
4742This example shows an empty string case.
4743 
4744```
4745strings.url_decode("") // ""
4746 
4747```
4748 
4749##### Example 3
4750 
4751This example shows non-alphabet characters handling.
4752 
4753```
4754strings.url_decode("%E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B") // "上海+中國"
4755 
4756```
4757 
4758##### Example 4
4759 
4760This example shows a sample URL decoding.
4761 
4762```
4763strings.url_decode("http://www.google.com%3Fparam1%3D%22+1+%3E+2+%22%26param2%3D2%3B") // 'http://www.google.com?param1="+1+>+2+"&param2=2;'
4764 
4765```
4766 
4767 
4768 
4769### timestamp.as\_unix\_seconds
4770 
4771Supported in:
4772 
4773[Rules](/chronicle/docs/detection/default-rules)
4774[Search](/chronicle/docs/investigation/udm-search)
4775 
4776```
4777timestamp.as_unix_seconds(timestamp [, time_zone])
4778 
4779```
4780 
4781#### Description
4782 
4783This function returns an integer representing the number of seconds past a Unix epoch for the given timestamp string.
4784 
4785* `timestamp` is a string representing a valid epoch timestamp. The format needs
4786 to be `%F %T`.
4787* `time_zone` is optional and is a string representing a time zone. If
4788 omitted, the default is `GMT`. You can specify time zones using string
4789 literals. The options are as follows:
4790 + The TZ database name, for example `America/Los_Angeles`. For more information, see the
4791 [list of tz database time zones on Wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
4792 + The time zone offset from UTC, in the format`(+|-)H[H][:M[M]]`,
4793 for example: "-08:00".
4794 
4795Here are examples of valid `time_zone` specifiers, which you can pass as the second argument to time extraction functions:
4796 
4797```
4798"America/Los_Angeles", or "-08:00". ("PST" is not supported)
4799"America/New_York", or "-05:00". ("EST" is not supported)
4800"Europe/London"
4801"UTC"
4802"GMT"
4803 
4804```
4805 
4806#### Param data types
4807 
4808`STRING`, `STRING`
4809 
4810#### Return type
4811 
4812`INT`
4813 
4814#### Code samples
4815 
4816##### Example 1
4817 
4818Valid epoch timestamp
4819 
4820```
4821timestamp.as_unix_seconds("2024-02-22 10:43:00") = 1708598580
4822 
4823```
4824 
4825##### Example 2
4826 
4827Valid epoch timestamp with the America/New\_York time zone
4828 
4829```
4830timestamp.as_unix_seconds("2024-02-22 10:43:00", "America/New_York") = 1708616580
4831 
4832```
4833 
4834 
4835 
4836### timestamp.current\_seconds
4837 
4838Supported in:
4839 
4840[Rules](/chronicle/docs/detection/default-rules)
4841[Search](/chronicle/docs/investigation/udm-search)
4842 
4843```
4844timestamp.current_seconds()
4845 
4846```
4847 
4848#### Description
4849 
4850Returns an integer representing the current time in Unix seconds. This is
4851approximately equal to the detection timestamp and is based on when the rule is
4852run. This function is a synonym of the function `timestamp.now()`.
4853 
4854#### Param data types
4855 
4856`NONE`
4857 
4858#### Return type
4859 
4860`INT`
4861 
4862#### Code samples
4863 
4864##### Example 1
4865 
4866The following example returns `true` if the certificate has been expired for more
4867than 24 hours. It calculates the time difference by subtracting the current Unix
4868seconds, and then comparing using a greater than operator.
4869 
4870```
487186400 < timestamp.current_seconds() - $e.network.tls.certificate.not_after
4872 
4873```
4874 
4875 
4876 
4877### timestamp.get\_date
4878 
4879Supported in:
4880 
4881[Rules](/chronicle/docs/detection/default-rules)
4882[Search](/chronicle/docs/investigation/udm-search)
4883 
4884```
4885timestamp.get_date(unix_seconds [, time_zone])
4886 
4887```
4888 
4889#### Description
4890 
4891This function returns a string in the format `YYYY-MM-DD`, representing the day a timestamp is in.
4892 
4893* `unix_seconds` is an integer representing the number of seconds past Unix
4894 epoch, such as `$e.metadata.event_timestamp.seconds`, or a placeholder
4895 containing that value.
4896* `time_zone` is optional and is a string representing a time\_zone. If
4897 omitted, the default is "GMT". You can specify time zones using string
4898 literals. The options are:
4899 + The TZ database name, for example "America/Los\_Angeles". For more
4900 information, see the ["TZ Database Name" column from this page](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
4901 + The time zone offset from UTC, in the format`(+|-)H[H][:M[M]]`,
4902 for example: "-08:00".
4903 
4904Here are examples of valid time\_zone specifiers, which you can pass as the second argument to time extraction functions:
4905 
4906```
4907"America/Los_Angeles", or "-08:00". ("PST" is not supported)
4908"America/New_York", or "-05:00". ("EST" is not supported)
4909"Europe/London"
4910"UTC"
4911"GMT"
4912 
4913```
4914 
4915#### Param data types
4916 
4917`INT`, `STRING`
4918 
4919#### Return type
4920 
4921`STRING`
4922 
4923#### Code samples
4924 
4925##### Example 1
4926 
4927In this example, the `time_zone` argument is omitted, so it defaults to "GMT".
4928 
4929```
4930$ts = $e.metadata.collected_timestamp.seconds
4931 
4932timestamp.get_date($ts) = "2024-02-19"
4933 
4934```
4935 
4936##### Example 2
4937 
4938This example uses a string literal to define the `time_zone`.
4939 
4940```
4941$ts = $e.metadata.collected_timestamp.seconds
4942 
4943timestamp.get_date($ts, "America/Los_Angeles") = "2024-02-20"
4944 
4945```
4946 
4947 
4948 
4949### timestamp.get\_minute
4950 
4951Supported in:
4952 
4953[Rules](/chronicle/docs/detection/default-rules)
4954[Search](/chronicle/docs/investigation/udm-search)
4955 
4956```
4957timestamp.get_minute(unix_seconds [, time_zone])
4958 
4959```
4960 
4961#### Description
4962 
4963This function returns an integer in the range `[0, 59]` representing the minute.
4964 
4965* `unix_seconds` is an integer representing the number of seconds past Unix
4966 epoch, such as `$e.metadata.event_timestamp.seconds`, or a placeholder
4967 containing that value.
4968* `time_zone` is optional and is a string representing a time zone. If
4969 omitted, the default is "GMT". You can specify time zones using string
4970 literals. The options are:
4971 + The TZ database name, for example "America/Los\_Angeles". For more
4972 information, see the ["TZ Database Name" column from this page](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
4973 + The time zone offset from UTC, in the format`(+|-)H[H][:M[M]]`,
4974 for example: "-08:00".
4975 
4976Here are examples of valid `time_zone` specifiers, which you can pass as the second argument to time extraction functions:
4977 
4978```
4979"America/Los_Angeles", or "-08:00". ("PST" is not supported)
4980"America/New_York", or "-05:00". ("EST" is not supported)
4981"Europe/London"
4982"UTC"
4983"GMT"
4984 
4985```
4986 
4987#### Param data types
4988 
4989`INT`, `STRING`
4990 
4991#### Return type
4992 
4993`INT`
4994 
4995#### Code samples
4996 
4997##### Example 1
4998 
4999In this example, the `time_zone` argument is omitted, so it defaults to "GMT".
5000 
5001```
5002$ts = $e.metadata.collected_timestamp.seconds
5003 
5004timestamp.get_hour($ts) = 15
5005 
5006```
5007 
5008##### Example 2
5009 
5010This example uses a string literal to define the `time_zone`.
5011 
5012```
5013$ts = $e.metadata.collected_timestamp.seconds
5014 
5015timestamp.get_hour($ts, "America/Los_Angeles") = 15
5016 
5017```
5018 
5019 
5020 
5021### timestamp.get\_hour
5022 
5023Supported in:
5024 
5025[Rules](/chronicle/docs/detection/default-rules)
5026[Search](/chronicle/docs/investigation/udm-search)
5027 
5028```
5029timestamp.get_hour(unix_seconds [, time_zone])
5030 
5031```
5032 
5033#### Description
5034 
5035This function returns an integer in the range `[0, 23]` representing the hour.
5036 
5037* `unix_seconds` is an integer representing the number of seconds past Unix
5038 epoch, such as `$e.metadata.event_timestamp.seconds`, or a placeholder
5039 containing that value.
5040* `time_zone` is optional and is a string representing a time zone. If
5041 omitted, the default is "GMT". You can specify time zones using string
5042 literals. The options are:
5043 + The TZ database name, for example "America/Los\_Angeles". For more
5044 information, see the ["TZ Database Name" column from this page](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
5045 + The time zone offset from UTC, in the format`(+|-)H[H][:M[M]]`,
5046 for example: "-08:00".
5047 
5048Here are examples of valid `time_zone` specifiers, which you can pass as the second argument to time extraction functions:
5049 
5050```
5051"America/Los_Angeles", or "-08:00". ("PST" is not supported)
5052"America/New_York", or "-05:00". ("EST" is not supported)
5053"Europe/London"
5054"UTC"
5055"GMT"
5056 
5057```
5058 
5059#### Param data types
5060 
5061`INT`, `STRING`
5062 
5063#### Return type
5064 
5065`INT`
5066 
5067#### Code samples
5068 
5069##### Example 1
5070 
5071In this example, the `time_zone` argument is omitted, so it defaults to "GMT".
5072 
5073```
5074$ts = $e.metadata.collected_timestamp.seconds
5075 
5076timestamp.get_hour($ts) = 15
5077 
5078```
5079 
5080##### Example 2
5081 
5082This example uses a string literal to define the `time_zone`.
5083 
5084```
5085$ts = $e.metadata.collected_timestamp.seconds
5086 
5087timestamp.get_hour($ts, "America/Los_Angeles") = 15
5088 
5089```
5090 
5091 
5092 
5093### timestamp.get\_day\_of\_week
5094 
5095Supported in:
5096 
5097[Rules](/chronicle/docs/detection/default-rules)
5098[Search](/chronicle/docs/investigation/udm-search)
5099 
5100```
5101timestamp.get_day_of_week(unix_seconds [, time_zone])
5102 
5103```
5104 
5105#### Description
5106 
5107This function returns an integer in the range `[1, 7]` representing the day of
5108week starting with Sunday. For example, 1 = Sunday and 2 = Monday.
5109 
5110* `unix_seconds` is an integer representing the number of seconds past Unix
5111 epoch, such as `$e.metadata.event_timestamp.seconds`, or a placeholder
5112 containing that value.
5113* `time_zone` is optional and is a string representing a time\_zone. If
5114 omitted, the default is "GMT". You can specify time zones using string
5115 literals. The options are:
5116 + The TZ database name, for example "America/Los\_Angeles". For more
5117 information, see the ["TZ Database Name" column from this page](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
5118 + The time zone offset from UTC, in the format`(+|-)H[H][:M[M]]`,
5119 for example: "-08:00".
5120 
5121Here are examples of valid time\_zone specifiers, which you can pass as the second argument to time extraction functions:
5122 
5123```
5124"America/Los_Angeles", or "-08:00". ("PST" is not supported)
5125"America/New_York", or "-05:00". ("EST" is not supported)
5126"Europe/London"
5127"UTC"
5128"GMT"
5129 
5130```
5131 
5132#### Param data types
5133 
5134`INT`, `STRING`
5135 
5136#### Return type
5137 
5138`INT`
5139 
5140#### Code samples
5141 
5142##### Example 1
5143 
5144In this example, the `time_zone` argument is omitted, so it defaults to "GMT".
5145 
5146```
5147$ts = $e.metadata.collected_timestamp.seconds
5148 
5149timestamp.get_day_of_week($ts) = 6
5150 
5151```
5152 
5153##### Example 2
5154 
5155This example uses a string literal to define the `time_zone`.
5156 
5157```
5158$ts = $e.metadata.collected_timestamp.seconds
5159 
5160timestamp.get_day_of_week($ts, "America/Los_Angeles") = 6
5161 
5162```
5163 
5164 
5165 
5166### timestamp.get\_timestamp
5167 
5168Supported in:
5169 
5170[Rules](/chronicle/docs/detection/default-rules)
5171[Search](/chronicle/docs/investigation/udm-search)
5172 
5173```
5174timestamp.get_timestamp(unix_seconds, optional timestamp_format/time_granularity, optional timezone)
5175 
5176```
5177 
5178#### Description
5179 
5180This function returns a string in the format `YYYY-MM-DD`, representing the day a timestamp is in.
5181 
5182* `unix_seconds` is an integer representing the number of seconds past Unix
5183 epoch, such as `$e.metadata.event_timestamp.seconds`, or a placeholder
5184 containing that value.
5185* `timestamp_format` is optional and is a string representing the format for the
5186 timestamp. If omitted, the default is `%F %T`. You can specify the format
5187 using a date time format string or one of the following time granularity:
5188 `SECOND`, `MINUTE`, `HOUR`, `DATE`, `WEEK`, `MONTH`, or `YEAR`.
5189 For more formatting options, see [Format elements for date and time parts](/bigquery/docs/reference/standard-sql/format-elements#format_elements_date_time)
5190* `time_zone` is optional and is a string representing a time zone. If
5191 omitted, the default is `GMT`. You can specify time zones using string
5192 literals. The options are as follows:
5193 + The IANA Time Zone (TZ) database name, for example, `America/Los_Angeles`. For more
5194 information, see the [list of tz database time zones on Wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
5195 + The time zone offset from UTC, in the format `(+|-)H[H][:M[M]]`,
5196 for example: "-08:00".
5197 
5198Here are examples of valid `time_zone` specifiers, which you can pass as the second argument to time extraction functions:
5199 
5200```
5201"America/Los_Angeles", or "-08:00". ("PST" is not supported)
5202"America/New_York", or "-05:00". ("EST" is not supported)
5203"Europe/London"
5204"UTC"
5205"GMT"
5206 
5207```
5208 
5209#### Param data types
5210 
5211`INT`, `STRING`, `STRING`
5212 
5213#### Return type
5214 
5215`STRING`
5216 
5217#### Code samples
5218 
5219##### Example 1
5220 
5221In this example, the `time_zone` argument is omitted, so it defaults to `GMT`.
5222 
5223```
5224$ts = $e.metadata.collected_timestamp.seconds
5225 
5226timestamp.get_timestamp($ts) = "2024-02-22 10:43:51"
5227 
5228```
5229 
5230##### Example 2
5231 
5232This example uses a string literal to define the `time_zone`.
5233 
5234```
5235$ts = $e.metadata.collected_timestamp.seconds
5236 
5237timestamp.get_timestamp($ts, "%F %T", "America/Los_Angeles") = "2024-02-22 10:43:51"
5238 
5239```
5240 
5241##### Example 3
5242 
5243This example uses a string literal to define the `timestamp_format`.
5244 
5245```
5246$ts = $e.metadata.collected_timestamp.seconds
5247 
5248timestamp.get_timestamp($ts, "%Y-%m", "GMT") = "2024-02"
5249 
5250```
5251 
5252##### Example 4
5253 
5254This example formats a unix timestamp as a string at second granularity.
5255 
5256```
5257timestamp.get_timestamp(1708598631, "SECOND", "GMT") = "2024-02-22 10:43:51"
5258 
5259```
5260 
5261##### Example 5
5262 
5263This example formats a unix timestamp as a string at minute granularity.
5264 
5265```
5266timestamp.get_timestamp(1708598631, "MINUTE", "GMT") = "2024-02-22 10:43"
5267 
5268```
5269 
5270##### Example 6
5271 
5272This example formats a unix timestamp as a string at hour granularity.
5273 
5274```
5275timestamp.get_timestamp(1708598631, "HOUR", "GMT") = "2024-02-22 10"
5276 
5277```
5278 
5279##### Example 7
5280 
5281This example formats a unix timestamp as a string at day granularity.
5282 
5283```
5284timestamp.get_timestamp(1708598631, "DATE", "GMT") = "2024-02-22"
5285 
5286```
5287 
5288##### Example 8
5289 
5290This example formats a unix timestamp as a string at week granularity.
5291 
5292```
5293timestamp.get_timestamp(1708598631, "WEEK", "GMT") = "2024-02-18"
5294 
5295```
5296 
5297##### Example 9
5298 
5299This example formats a unix timestamp as a string at month granularity.
5300 
5301```
5302timestamp.get_timestamp(1708598631, "MONTH", "GMT") = "2024-02"
5303 
5304```
5305 
5306##### Example 10
5307 
5308This example formats a unix timestamp as a string at year granularity.
5309 
5310```
5311timestamp.get_timestamp(1708598631, "YEAR", "GMT") = "2024"
5312 
5313```
5314 
5315 
5316 
5317### timestamp.get\_week
5318 
5319Supported in:
5320 
5321[Rules](/chronicle/docs/detection/default-rules)
5322[Search](/chronicle/docs/investigation/udm-search)
5323 
5324```
5325timestamp.get_week(unix_seconds [, time_zone])
5326 
5327```
5328 
5329#### Description
5330 
5331This function returns an integer in the range `[0, 53]` representing the week of
5332the year. Weeks begin with Sunday. Dates before the first Sunday of the year are
5333in week 0.
5334 
5335* `unix_seconds` is an integer representing the number of seconds past Unix
5336 epoch, such as `$e.metadata.event_timestamp.seconds`, or a placeholder
5337 containing that value.
5338* `time_zone` is optional and is a string representing a time zone. If
5339 omitted, the default is "GMT". You can specify time zones using string
5340 literals. The options are:
5341 + The TZ database name, for example "America/Los\_Angeles". For more
5342 information, see the ["TZ Database Name" column from this page](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
5343 + The time zone offset from UTC, in the format`(+|-)H[H][:M[M]]`,
5344 for example: "-08:00".
5345 
5346Here are examples of valid `time_zone` specifiers, which you can pass as the second argument to time extraction functions:
5347 
5348```
5349"America/Los_Angeles", or "-08:00". ("PST" is not supported)
5350"America/New_York", or "-05:00". ("EST" is not supported)
5351"Europe/London"
5352"UTC"
5353"GMT"
5354 
5355```
5356 
5357#### Param data types
5358 
5359`INT`, `STRING`
5360 
5361#### Return type
5362 
5363`INT`
5364 
5365#### Code samples
5366 
5367##### Example 1
5368 
5369In this example, the `time_zone` argument is omitted, so it defaults to "GMT".
5370 
5371```
5372$ts = $e.metadata.collected_timestamp.seconds
5373 
5374timestamp.get_week($ts) = 0
5375 
5376```
5377 
5378##### Example 2
5379 
5380This example uses a string literal to define the `time_zone`.
5381 
5382```
5383$ts = $e.metadata.collected_timestamp.seconds
5384 
5385timestamp.get_week($ts, "America/Los_Angeles") = 0
5386 
5387```
5388 
5389 
5390 
5391### timestamp.now
5392 
5393Supported in:
5394 
5395[Rules](/chronicle/docs/detection/default-rules)
5396[Search](/chronicle/docs/investigation/udm-search)
5397 
5398```
5399timestamp.now()
5400 
5401```
5402 
5403#### Description
5404 
5405Returns the number of seconds since 1970-01-01 00:00:00 UTC. This is also
5406known as *Unix epoch time*.
5407 
5408#### Return type
5409 
5410`INT`
5411 
5412#### Code samples
5413 
5414##### Example 1
5415 
5416The following example returns a timestamp for code executed on
5417May 22, 2024 at 18:16:59.
5418 
5419```
5420timestamp.now() = 1716401819 // Unix epoch time in seconds for May 22, 2024 at 18:16:59
5421 
5422```
5423 
5424 
5425 
5426### window.avg
5427 
5428Supported in:
5429 
5430[Rules](/chronicle/docs/detection/default-rules)
5431 
5432```
5433window.avg(numeric_values [, should_ignore_zero_values])
5434 
5435```
5436 
5437#### Description
5438 
5439Returns the average of the input values (which can be Integers or Floats). Setting the optional second argument to true ignores zero values.
5440 
5441#### Param data types
5442 
5443`INT|FLOAT`
5444 
5445#### Return type
5446 
5447`FLOAT`
5448 
5449#### Code samples
5450 
5451##### Example 1
5452 
5453This example shows the integer average.
5454 
5455```
5456// This rule sets the outcome $size_mode to the average
5457// file size in the 5 minute match window.
5458events:
5459 $e.user.userid = $userid
5460match:
5461 $userid over 5m
5462outcome:
5463 $size_mode = window.avg($e.file.size) // yields 2.5 if the event file size values in the match window are 1, 2, 3 and 4
5464 
5465```
5466 
5467##### Example 2
5468 
5469This example shows the float average.
5470 
5471```
5472events:
5473 $e.user.userid = $userid
5474match:
5475 $userid over 5m
5476outcome:
5477 $size_mode = window.avg($e.file.size) // yields 1.75 if the event file size values in the match window are 1.1 and 2.4
5478 
5479```
5480 
5481##### Example 3
5482 
5483Negative input average
5484 
5485```
5486events:
5487 $e.user.userid = $userid
5488match:
5489 $userid over 5m
5490outcome:
5491 $size_mode = window.avg($e.file.size) // yields 0.6 if the event file size values in the match window are -1.1, 1.1, 0.0 and 2.4
5492 
5493```
5494 
5495##### Example 4
5496 
54970 returns 0
5498 
5499```
5500events:
5501 $e.user.userid = $userid
5502match:
5503 $userid over 5m
5504outcome:
5505 $size_mode = window.avg($e.file.size) // yields 0 if the event file size values in the match window is 0
5506 
5507```
5508 
5509##### Example 5
5510 
5511Ignoring 0 values
5512 
5513```
5514events:
5515 $e.user.userid = $userid
5516match:
5517 $userid over 5m
5518outcome:
5519 $size_mode = window.avg($e.file.size, true) // yields 394 if the event file size values in the match window are 0, 0, 0 and 394
5520 
5521```
5522 
5523 
5524 
5525### window.first
5526 
5527Supported in:
5528 
5529[Rules](/chronicle/docs/detection/default-rules)
5530 
5531```
5532window.first(values_to_sort_by, values_to_return)
5533 
5534```
5535 
5536#### Description
5537 
5538This aggregation function returns a string value derived from an event with the lowest correlated int value in the match window. An example use case is getting the userid from the event with the lowest timestamp in the match window (earliest event).
5539 
5540#### Param data types
5541 
5542`INT`, `STRING`
5543 
5544#### Return type
5545 
5546`STRING`
5547 
5548#### Code samples
5549 
5550Get a string value derived from an event with the lowest correlated int value in the match window.
5551 
5552```
5553// This rule sets the outcome $first_event to the lowest correlated int value
5554// in the 5 minute match window.
5555events:
5556 $e.user.userid = $userid
5557match:
5558 $userid over 5m
5559outcome:
5560 $first_event = window.first($e.metadata.timestamp.seconds, $e.metadata.event_type) // yields v1 if the events in the match window are 1, 2 and 3 and corresponding values v1, v2, and v3.
5561 
5562```
5563 
5564 
5565 
5566### window.last
5567 
5568Supported in:
5569 
5570[Rules](/chronicle/docs/detection/default-rules)
5571 
5572```
5573window.last(values_to_sort_by, values_to_return)
5574 
5575```
5576 
5577#### Description
5578 
5579This aggregation function returns a string value derived from an event with the highest correlated int value in the match window. An example use case is getting the userid from the event with the lowest timestamp in the match window (highest timestamp).
5580 
5581#### Param data types
5582 
5583`INT`, `STRING`
5584 
5585#### Return type
5586 
5587`STRING`
5588 
5589#### Code samples
5590 
5591Get a string value derived from an event with the highest correlated int value in the match window.
5592 
5593```
5594// This rule sets the outcome $last_event to the highest correlated int value
5595// in the 5 minute match window.
5596events:
5597 $e.user.userid = $userid
5598match:
5599 $userid over 5m
5600outcome:
5601 $last_event = window.first($e.metadata.timestamp.seconds, $e.metadata.event_type) // yields v3 if the events in the match window are 1, 2 and 3 and corresponding values v1, v2, and v3.
5602 
5603```
5604 
5605 
5606 
5607### window.median
5608 
5609Supported in:
5610 
5611[Rules](/chronicle/docs/detection/default-rules)
5612 
5613```
5614window.median(numeric_values, should_ignore_zero_values)
5615 
5616```
5617 
5618#### Description
5619 
5620Return the median of the input values. If there are 2 median values, only 1 will be non-deterministically chosen as the return value.
5621 
5622#### Param data types
5623 
5624`INT|FLOAT`, `BOOL`
5625 
5626#### Return type
5627 
5628`FLOAT`
5629 
5630#### Code samples
5631 
5632##### Example 1
5633 
5634This example returns the median when the input values aren't zero.
5635 
5636```
5637rule median_file_size {
5638 meta:
5639 events:
5640 $e.metadata.event_type = "FILE_COPY"
5641 $userid = $e.principal.user.userid
5642 match:
5643 $userid over 1h
5644 outcome:
5645 $median_file_size = window.median($e.principal.file.size) // returns 2 if the file sizes in the match window are [1, 2, 3]
5646 condition:
5647 $e
5648}
5649 
5650```
5651 
5652##### Example 2
5653 
5654This example returns the median when the input includes some zero values that shouldn't be ignored.
5655 
5656```
5657rule median_file_size {
5658 meta:
5659 events:
5660 $e.metadata.event_type = "FILE_COPY"
5661 $userid = $e.principal.user.userid
5662 match:
5663 $userid over 1h
5664 outcome:
5665 $median_file_size = window.median($e.principal.file.size) // returns 1 if the file sizes in the match window are [0,0, 1, 2, 3]
5666 condition:
5667 $e
5668}
5669 
5670```
5671 
5672##### Example 3
5673 
5674This example returns the median when the input includes some zero values which should be ignored.
5675 
5676```
5677rule median_file_size {
5678 meta:
5679 events:
5680 $e.metadata.event_type = "FILE_COPY"
5681 $userid = $e.principal.user.userid
5682 match:
5683 $userid over 1h
5684 outcome:
5685 $median_file_size = window.median($e.principal.file.size, true) // returns 2 if the file sizes in the match window are [0,0, 1, 2, 3]
5686 condition:
5687 $e
5688}
5689 
5690```
5691 
5692##### Example 4
5693 
5694This example returns the median when the input includes all zero values which should be ignored.
5695 
5696```
5697rule median_file_size {
5698 meta:
5699 events:
5700 $e.metadata.event_type = "FILE_COPY"
5701 $userid = $e.principal.user.userid
5702 match:
5703 $userid over 1h
5704 outcome:
5705 $median_file_size = window.median($e.principal.file.size) // returns 0 if the file sizes in the match window are [0,0]
5706 condition:
5707 $e
5708}
5709 
5710```
5711 
5712##### Example 5
5713 
5714This example shows that, when there are multiple medians, only one median is returned.
5715 
5716```
5717rule median_file_size {
5718 meta:
5719 events:
5720 $e.metadata.event_type = "FILE_COPY"
5721 $userid = $e.principal.user.userid
5722 match:
5723 $userid over 1h
5724 outcome:
5725 $median_file_size = window.median($e.principal.file.size) // returns 1 if the file sizes in the match window are [1, 2, 3, 4]
5726 condition:
5727 $e
5728}
5729 
5730```
5731 
5732 
5733 
5734### window.mode
5735 
5736Supported in:
5737 
5738[Rules](/chronicle/docs/detection/default-rules)
5739 
5740```
5741window.mode(values)
5742 
5743```
5744 
5745#### Description
5746 
5747Return the mode of the input values. In case of multiple possible mode values, only one of those values will be non-deterministically chosen as the return value.
5748 
5749#### Param data types
5750 
5751`INT|FLOAT|STRING`
5752 
5753#### Return type
5754 
5755`STRING`
5756 
5757#### Code samples
5758 
5759##### Example 1
5760 
5761Get mode of the values in the match window.
5762 
5763```
5764// This rule sets the outcome $size_mode to the most frequently occurring
5765// file size in the 5 minute match window.
5766events:
5767 $e.user.userid = $userid
5768match:
5769 $userid over 5m
5770outcome:
5771 $size_mode = window.mode($e.file.size) // yields 1.6 if the event file size values in the match window are 1.6, 2, and 1.6
5772 
5773```
5774 
5775 
5776 
5777### window.stddev
5778 
5779Supported in:
5780 
5781[Rules](/chronicle/docs/detection/default-rules)
5782 
5783```
5784window.stddev(numeric_values)
5785 
5786```
5787 
5788#### Description
5789 
5790Returns the standard deviation of input values in a match window.
5791 
5792#### Param data types
5793 
5794`INT|FLOAT`
5795 
5796#### Return type
5797 
5798`FLOAT`
5799 
5800#### Code samples
5801 
5802##### Example 1
5803 
5804This example returns the standard deviation of integers in a match window.
5805 
5806```
5807// This rule creates a detection when the file size stddev in 5 minutes for a user is over a threshold.
5808events:
5809 $e.user.userid = $userid
5810match:
5811 $userid over 5m
5812outcome:
5813 $p1 = window.stddev($e.file.size) // yields 4.0 if the event file size values in the match window are [10, 14, 18].
5814condition:
5815 $e and #p1 > 2
5816 
5817```
5818 
5819##### Example 2
5820 
5821This example returns the standard deviation of floats in a match window.
5822 
5823```
5824events:
5825 $e.user.userid = $userid
5826match:
5827 $userid over 5m
5828outcome:
5829 $p1 = window.stddev($e.file.size) // yields 4.488686 if the event file size values in the match window are [10.00, 14.80, 18.97].
5830condition:
5831 $e and #p1 > 2
5832 
5833```
5834 
5835##### Example 3
5836 
5837This example returns the standard deviation in a match window that contains negative numbers.
5838 
5839```
5840events:
5841 $e.user.userid = $userid
5842match:
5843 $userid over 5m
5844outcome:
5845 $p1 = window.stddev($e.file.size) // yields 48.644972 if the event file size values in the match window are [-1, -56, -98].
5846condition:
5847 $e and #p1 > 2
5848 
5849```
5850 
5851##### Example 4
5852 
5853This example returns with zero standard deviation when all values in the match window are the same.
5854 
5855```
5856events:
5857 $e.user.userid = $userid
5858match:
5859 $userid over 5m
5860outcome:
5861 $p1 = window.stddev($e.file.size) // yields 0.000000 if the event file size values in the match window are [1, 1, 1].
5862condition:
5863 $e and #p1 > 2
5864 
5865```
5866 
5867##### Example 5
5868 
5869This example returns the standard deviation of a match window containing positive and negative numbers.
5870 
5871```
5872events:
5873 $e.user.userid = $userid
5874match:
5875 $userid over 5m
5876outcome:
5877 $p1 = window.stddev($e.file.size) // yields 1.000000 if the event file size values in the match window are [1, 0, -1].
5878condition:
5879 $e and #p1 > 10
5880 
5881```
5882 
5883 
5884 
5885### window.variance
5886 
5887Supported in:
5888 
5889[Rules](/chronicle/docs/detection/default-rules)
5890 
5891```
5892window.variance(values)
5893 
5894```
5895 
5896#### Description
5897 
5898This function returns the specified variance of the input values.
5899 
5900#### Param data types
5901 
5902`INT|FLOAT`
5903 
5904#### Return type
5905 
5906`FLOAT`
5907 
5908#### Code samples
5909 
5910##### Example 1
5911 
5912This example returns the variance of all integers.
5913 
5914```
5915// This rule creates a detection when the file size variance in 5 minutes for a user is over a threshold.
5916events:
5917 $e.user.userid = $userid
5918match:
5919 $userid over 5m
5920outcome:
5921 $p1 = window.variance($e.file.size) // yields 16 if the event file size values in the match window are [10, 14, 18].
5922condition:
5923 $e and #p1 > 10
5924 
5925```
5926 
5927##### Example 2
5928 
5929This example returns the variance of all floats.
5930 
5931```
5932events:
5933 $e.user.userid = $userid
5934match:
5935 $userid over 5m
5936outcome:
5937 $p1 = window.variance($e.file.size) // yields 20.148300 if the event file size values in the match window are [10.00, 14.80, 18.97].
5938condition:
5939 $e and #p1 > 10
5940 
5941```
5942 
5943##### Example 3
5944 
5945This example returns the variance of negative numbers.
5946 
5947```
5948events:
5949 $e.user.userid = $userid
5950match:
5951 $userid over 5m
5952outcome:
5953 $p1 = window.variance($e.file.size) // yields 2366.333333 if the event file size values in the match window are [-1, -56, -98].
5954condition:
5955 $e and #p1 > 10
5956 
5957```
5958 
5959##### Example 4
5960 
5961This example returns a small variance value.
5962 
5963```
5964events:
5965 $e.user.userid = $userid
5966match:
5967 $userid over 5m
5968outcome:
5969 $p1 = window.variance($e.file.size) // yields 0.000000 if the event file size values in the match window are [0.000000, 0.000000, 0.000100].
5970condition:
5971 $e and #p1 > 10
5972 
5973```
5974 
5975##### Example 5
5976 
5977This example returns a zero variance.
5978 
5979```
5980events:
5981 $e.user.userid = $userid
5982match:
5983 $userid over 5m
5984outcome:
5985 $p1 = window.variance($e.file.size) // yields 0.000000 if the event file size values in the match window are [1, 1, 1].
5986condition:
5987 $e and #p1 > 10
5988 
5989```
5990 
5991##### Example 6
5992 
5993This example returns the variance of positive and negative numbers.
5994 
5995```
5996events:
5997 $e.user.userid = $userid
5998match:
5999 $userid over 5m
6000outcome:
6001 $p1 = window.variance($e.file.size) // yields 1.000000 if the event file size values in the match window are [1, 0, -1].
6002condition:
6003 $e and #p1 > 10
6004 
6005```
6006 
6007 
6008 
6009### bytes.to\_base64
6010 
6011Supported in:
6012 
6013[Rules](/chronicle/docs/detection/default-rules)
6014[Search](/chronicle/docs/investigation/udm-search)
6015 
6016```
6017bytes.to_base64(bytes, optional_default_string)
6018 
6019```
6020 
6021#### Description
6022 
6023Function converts a `bytes` value to a `base64 encoded string`. Function calls with values that cannot be casted return an empty string by default.
6024 
6025#### Param data types
6026 
6027`BYTES`, `STRING`
6028 
6029#### Return type
6030 
6031`STRING`
6032 
6033#### Code samples
6034 
6035##### Raw Binary Bytes to Base64 Encoded String
6036 
6037The function converts the raw binary bytes to base64 encoded string.
6038 
6039```
6040bytes.to_base64(b'000000006f8ec5586d026f9ddac56e9f2fe15b8a0000000001000000cd000000) = "AAAAAG+OxVhtAm+d2sVuny/hW4oAAAAAAQAAAM0AAAA="
6041 
6042```
6043 
6044##### Failed Conversion (Defaults to the Optionally Provided String)
6045 
6046The function defaults to the `"invalid bytes"` when the bytes value provided isn't valid.
6047 
6048```
6049bytes.to_base64(b'000000006f8ec5586d", "invalid bytes") = "invalid bytes"
6050 
6051```
6052 
6053## Function to placeholder assignment
6054 
6055You can assign the result of a function call to a placeholder in the `events` section. For example:
6056 
6057`$placeholder = strings.concat($e.principal.hostname, "my-string").`
6058 
6059You can then use the placeholder variables in the `match`, `condition`, and `outcome` sections.
6060However, there are two limitations with function to placeholder assignment:
6061 
60621. Every placeholder in function to placeholder assignment must be assigned to an expression containing an event field. For example, the following examples are valid:
6063 
6064```
6065 $ph1 = $e.principal.hostname
6066 $ph2 = $e.src.hostname
6067 
6068 // Both $ph1 and $ph2 have been assigned to an expression containing an event field.
6069 $ph1 = strings.concat($ph2, ".com")
6070 
6071```
6072 
6073```
6074 $ph1 = $e.network.email.from
6075 $ph2 = strings.concat($e.principal.hostname, "@gmail.com")
6076 
6077 // Both $ph1 and $ph2 have been assigned to an expression containing an event field.
6078 $ph1 = strings.to_lower($ph2)
6079 
6080```
6081 
6082 However, the following example is invalid:
6083 
6084```
6085 $ph1 = strings.concat($e.principal.hostname, "foo")
6086 $ph2 = strings.concat($ph1, "bar") // $ph2 has NOT been assigned to an expression containing an event field.
6087 
6088```
60892. Function call should depend on **one and exactly one** event.
6090 However, more than one field from the same event can be used in function call arguments.
6091 For example, the following is valid:
6092 
6093 `$ph = strings.concat($event.principal.hostname, "string2")`
6094 
6095 `$ph = strings.concat($event.principal.hostname, $event.src.hostname)`
6096 
6097 However, the following is invalid:
6098 
6099 `$ph = strings.concat("string1", "string2")`
6100 
6101 `$ph = strings.concat($event.principal.hostname, $anotherEvent.src.hostname)`
6102 
6103## Reference Lists syntax
6104 
6105See our [page on Reference Lists](https://cloud.google.com/chronicle/docs/reference/reference-lists.md) for more information on
6106reference list behavior and reference list syntax.
6107 
6108You can use reference lists in the `events` or `outcome` sections. Here is the
6109syntax for using various types of reference lists in a rule:
6110 
6111```
6112// STRING reference list
6113$e.principal.hostname in %string_reference_list
6114 
6115// REGEX reference list
6116$e.principal.hostname in regex %regex_reference_list
6117 
6118// CIDR reference list
6119$e.principal.ip in cidr %cidr_reference_list
6120 
6121 
6122```
6123 
6124You can also use the `not` operator and the `nocase` operator with reference lists as shown in the following example:
6125 
6126```
6127// Exclude events whose hostnames match substrings in my_regex_list.
6128not $e.principal.hostname in regex %my_regex_list
6129 
6130// Event hostnames must match at least 1 string in my_string_list (case insensitive).
6131$e.principal.hostname in %my_string_list nocase
6132 
6133```
6134 
6135The `nocase` operator is compatible with `STRING` lists and `REGEX` lists.
6136 
6137For performance reasons, the Detection Engine restricts reference list usage.
6138 
6139* Maximum `in` statements in a rule, with or without special operators: 7
6140* Maximum `in` statements with the `regex` operator: 4
6141* Maximum `in` statements with the `cidr` operator: 2
6142 
6143## Type checking
6144 
6145Google SecOps performs type checking against your YARA-L syntax as you create rules within the interface. The type checking errors displayed help you to revise the rule in such a way as to ensure that it will work as expected.
6146 
6147The following are examples of **invalid** predicates:
6148 
6149```
6150// $e.target.port is of type integer which cannot be compared to a string.
6151$e.target.port = "80"
6152 
6153// "LOGIN" is not a valid event_type enum value.
6154$e.metadata.event_type = "LOGIN"
6155 
6156```
6157 
6158## Detection Event Sampling
6159 
6160Detections from multi-event rules contain event samples to provide context
6161about the events that caused the detection. There is a limit of up to 10 event
6162samples for each event variable defined in the rule. For example, if a rule
6163defines 2 event variables, each detection can have up to 20 event samples. The
6164limit applies to each event variable separately. If one event variable has
61652 applicable events in this detection, and the other event variable has 15
6166applicable events, the resulting detection contains 12 event samples (2 + 10).
6167 
6168Any event samples over the limit are omitted from the detection.
6169 
6170If you want more information about the events that caused your detection,
6171you can use aggregations in the [outcome section](#outcome_section_syntax)
6172to output additional information in your detection.
6173 
6174If you are viewing detections in the UI, you can download all events samples
6175for a detection. For more information, see [Download events](/chronicle/docs/detection/downloading-events).
6176 
6177Last updated 2025-06-08 UTC.
6178 

Sections

  • YARA-L 2.0 language syntax
  • Rule structure
  • Meta section syntax
  • Events section syntax
  • Variable declarations
  • Event variable filters
  • Event variable joins
  • Match section syntax
  • Zero value handling in the match section
  • Hop window
  • Sliding window
  • Outcome section syntax
  • Outcome variable data types
  • Conditional logic
  • Mathematical operations
  • Placeholder variables in outcomes
  • Outcome variables in outcome assignment expressions
  • Aggregations
  • Condition section syntax
  • Count character
  • Value character
  • Event and placeholder conditionals
  • Bounded and Unbounded conditions
  • Outcome conditionals
  • Options section syntax
  • allow\_zero\_values
  • suppression\_window
  • Composite detection rules
  • Rule structure
  • Use detections as input to rules
  • Combine events and detections
  • Create sequential composite detections
  • Boolean expressions
  • Comparisons
  • Functions
  • Reference list expressions
  • Logical expressions
  • Enumerated types
  • Nocase Modifier
  • Repeated fields
  • Repeated fields and boolean expressions
  • Repeated fields and placeholders
  • Array indexing
  • Repeated messages
  • Comments
  • Literals
  • String and regular expression literals
  • Operators
  • Variables
  • Keywords
  • Maps
  • Functions
  • arrays.concat
  • arrays.join\_string
  • arrays.length
  • arrays.max
  • arrays.min
  • arrays.size
  • arrays.index\_to\_float
  • arrays.index\_to\_int

What it covers

architecturetypesdo-notdocs

Stack — with the evidence

python

(0.80)

node

(0.70)

pytest

(0.70)

typescript

(0.60)

github-actions

(0.60)

javascript

(0.50)

Format

Cline rules

A single file or a folder of files, all always-on. The folder form is the simplest way any format here lets you split rules into topics without also learning an activation model.

What the corpus says about it

Repository

Owner
repulsivityy
Language
—
License
—
Archived
no

All configs in this repo

Also in repulsivityy/elevate_2025

Diff this repo’s formats

One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
repulsivityy/elevate_2025.clinerules/OVERVIEW_OF_YARAL_LANGUAGE.md · 2Cline rulespythonnode+4archdo-not45/1003 days ago
repulsivityy/elevate_2025.clinerules/YARA_RULES_STYLE_GUIDE.md · 2Cline rulespythonnode+4buildstylearchtypes46/1003 days ago
repulsivityy/elevate_2025ai-runbooks-elevate25/.clinerules/suggested_mcp_tools.md · 2Cline rulespythonnode+4no sections34/1003 days ago
repulsivityy/elevate_2025.clinerules/SECOPS_YARAL_STYLE_GUIDE.md · 2Cline rulespythonnode+4lint-formatstyledo-not61/1003 days ago
repulsivityy/elevate_2025.clinerules/coding_conventions.md · 2Cline rulespythonnode+4styledocs34/1003 days ago
repulsivityy/elevate_2025.clinerules/project_plan.md · 2Cline rulespythonnode+4agent-behaviour26/1003 days ago
repulsivityy/elevate_2025.clinerules/readme.md · 2Cline rulespythonnode+4setuparch52/1003 days ago
repulsivityy/elevate_2025.clinerules/reporting_templates.md · 2Cline rulespythonnode+4typessecurity44/1003 days ago
repulsivityy/elevate_2025.clinerules/suggested_mcp_tools.md · 2Cline rulespythonnode+4no sections34/1003 days ago
repulsivityy/elevate_2025ai-runbooks-elevate25/.clinerules/coding_conventions.md · 2Cline rulespythonnode+4styledocs34/1003 days ago
repulsivityy/elevate_2025ai-runbooks-elevate25/.clinerules/project_plan.md · 2Cline rulespythonnode+4agent-behaviour26/1003 days ago
repulsivityy/elevate_2025ai-runbooks-elevate25/.clinerules/readme.md · 2Cline rulespythonnode+4setuparch52/1003 days ago
repulsivityy/elevate_2025ai-runbooks-elevate25/.clinerules/reporting_templates.md · 2Cline rulespythonnode+4typessecurity44/1003 days ago
Diff against .clinerules/OVERVIEW_OF_YARAL_LANGUAGE.md Diff against .clinerules/YARA_RULES_STYLE_GUIDE.md Diff against ai-runbooks-elevate25/.clinerules/suggested_mcp_tools.md Diff against .clinerules/SECOPS_YARAL_STYLE_GUIDE.md Diff against .clinerules/coding_conventions.md Diff against .clinerules/project_plan.md Diff against .clinerules/readme.md Diff against .clinerules/reporting_templates.md Diff against .clinerules/suggested_mcp_tools.md Diff against ai-runbooks-elevate25/.clinerules/coding_conventions.md Diff against ai-runbooks-elevate25/.clinerules/project_plan.md Diff against ai-runbooks-elevate25/.clinerules/readme.md Diff against ai-runbooks-elevate25/.clinerules/reporting_templates.md

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
bashdeban/fastmind.clinerules/.project-consistency-keeper2.md · 5Cline rulestypescriptnode+8setupbuildtestlint-format+11100/1003 days ago
JCodesMore/ai-website-cloner-template.clinerules · 31kCline rulestypescriptnode+7buildlint-formatstylearch+397/1002 days ago
BryaanF/LiantPortfolio.clinerules/project-guidelines.md · 0Cline rulesjavascripttailwind+5buildstylearchgit+296/1003 days ago
u9401066/zotero-keeper.clinerules/50-pubmed-project.md · 6Cline rulespytestruff+6testlint-formatstylearch+194/1003 days ago
u9401066/zotero-keepervscode-extension/resources/repo-assets/pubmed-search-mcp/.clinerules/50-pubmed-project.md · 6Cline rulespytestruff+6testlint-formatstylearch+194/1003 days ago
u9401066/pubmed-search-mcp.clinerules/50-pubmed-project.md · 23Cline rulespythondocker+4testlint-formatstylearch+194/1003 days ago
HerringtonDarkholme/megarepo.clinerules/02-development.md · 17Cline rulesnodejavascriptsetupbuildteststyle+392/1003 days ago
blendsdk/codeops-mcp.clinerules/project.md · 0Cline rulestypescriptvitest+3buildteststylearch+791/1003 days ago
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack