Cline rules
.clinerules/YARAL_SYNTAX.mdCline rules
Quality
45/100
Scores the file, not the repository.Length
20,652 words
600 headings · 342 code blocksRepository
2
— · pushed 178 days agoLast changed
3 days ago
First indexed 3 days ago.12# YARA-L 2.0 language syntax34Supported in:56Google secops7[Siem](/chronicle/docs/secops/google-secops-siem-toc)89This 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).1011**Note:** YARA-L syntax doesn't allow negative integers. For example,12`$e.principal.ip[-1]` is not valid. Replace `-1` with `0-1`.1314## Rule structure1516For YARA-L 2.0, you must specify variable declarations, definitions, and usages in the following order:17181. meta192. events203. match (optional)214. outcome (optional)225. condition236. options (optional)2425**Note:** If you exclude `match`, the rule can match against a single event.2627The following example illustrates the generic structure of a rule:2829```30rule <rule Name>31{32 meta:33 // Stores arbitrary key-value pairs of rule details, such as who wrote34 // it, what it detects on, version control, etc.3536 events:37 // Conditions to filter events and the relationship between events.3839 match:40 // Values to return when matches are found.4142 outcome:43 // Additional information extracted from each detection.4445 condition:46 // Condition to check events and the variables used to find matches.4748 options:49 // Options to turn on or off while executing this rule.50}5152```5354## Meta section syntax5556Meta 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:5758`<key> = "<value>"`5960The following is an example of a valid `meta` section line:6162```63meta:64 author = "Google"65 severity = "HIGH"6667```6869## Events section syntax7071In the `events` section, list the predicates to specify the following:7273* Variable declarations74* Event variable filters75* Event variable joins7677### Variable declarations7879For variable declarations, use the following syntax:8081* `<EVENT_FIELD> = <VAR>`82* `<VAR> = <EVENT_FIELD>`8384Both are equivalent, as shown in the following examples:8586* `$e.source.hostname = $hostname`87* `$userid = $e.principal.user.userid`8889This 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.9091For example, the following:9293* `$e1.source.ip = $ip`94* `$e2.target.ip = $ip`9596Are equivalent to:9798* `$e1.source.ip = $ip`99* `$e1.source.ip = $e2.target.ip`100101When 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.102103### Event variable filters104105A [boolean expression](#boolean_expressions) that acts on a single event variable is considered a filter.106107### Event variable joins108109All event variables used in the rule must be joined with every other event variable in either of the following ways:110111* 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.113114For example, assuming $e1, $e2, and $e3 are used in the rule, the following `events` sections are valid.115116```117events:118 $e1.principal.hostname = $e2.src.hostname // $e1 joins with $e2119 $e2.principal.ip = $e3.src.ip // $e2 joins with $e3120121```122123```124events:125 // $e1 joins with $e2 via function to event comparison126 re.capture($e1.src.hostname, ".*") = $e2.target.hostname127128```129130```131events:132 // $e1 joins with $e2 via an `or` expression133 $e1.principal.hostname = $e2.src.hostname134 or $e1.principal.hostname = $e2.target.hostname135 or $e1.principal.hostname = $e2.principal.hostname136137```138139```140events:141 // all of $e1, $e2 and $e3 are transitively joined via the placeholder variable $ip142 $e1.src.ip = $ip143 $e2.target.ip = $ip144 $e3.about.ip = $ip145146```147148```149events:150 // $e1 and $e2 are transitively joined via function to event comparison151 re.capture($e2.principal.application, ".*") = $app152 $e1.principal.hostname = $app153154```155156**Note:** If your sole join condition is an `or` chain, a function to event157comparison, or a combination of both, then the rule may perform poorly.158159However, here are examples of invalid `events` sections.160161```162events:163 // Event to arithmetic comparison is an invalid join condition for $e1 and $e2.164 $e1.principal.port = $e2.src.port + 1165166```167168```169events:170 $e1.src.ip = $ip171 $e2.target.ip = $ip172 $e3.about.ip = "192.1.2.0" //$e3 is not joined with $e1 or $e2.173174```175176```177events:178 $e1.src.port = $port179180 // Arithmetic to placeholder comparison is an invalid transitive join condition.181 $e2.principal.port + 800 = $port182183```184185## Match section syntax186187In the `match` section, list the match variables for group events before checking for match conditions. Those fields are returned with each match.188189* 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>`192193 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.196197The following is an example of a valid `match`:198199```200$var1, $var2 over 5m201202```203204This 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.205206Here is another example of a valid `match` section:207208```209$user over 1h210211```212213This 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.214215Here is another example of a valid `match` section:216217```218$source_ip, $target_ip, $hostname over 2m219220```221222This 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.223224The following examples illustrate **invalid** `match` sections:225226* `var1, var2 over 5m // invalid variable name`227* `$user 1h // missing keyword`228229### Zero value handling in the match section230231Rules Engine implicitly filters out the zero values for all placeholders that232are used in the match section (`""` for233string, `0` for numbers, `false` for booleans, the value in position 0234for [enumerated types](/chronicle/docs/reference/udm-field-list#event_enumerated_types)).235The following example illustrates rules that filter out the zero values.236237```238rule ZeroValuePlaceholderExample {239 meta:240 events:241 // Because $host is used in the match section, the rule behaves242 // as if the following predicate was added to the events section:243 // $host != ""244 $host = $e.principal.hostname245246 // Because $otherPlaceholder was not used in the match section,247 // there is no implicit filtering of zero values for $otherPlaceholder.248 $otherPlaceholder = $e.principal.ip249250 match:251 $host over 5m252253 condition:254 $e255}256257```258259However, if a placeholder is assigned to a function, rules don't260implicitly filter out the zero values of placeholders that are used in261the match section.262The following example illustrates rules that filter out the zero values:263264```265rule ZeroValueFunctionPlaceholder {266 meta:267 events:268 // Even though $ph is used in the match section, there is no269 // implicit filtering of zero values for $ph, because $ph is assigned to a function.270 $ph = re.capture($e.principal.hostname, "some-regex")271272 match:273 $ph over 5m274275 condition:276 $e277}278279```280281To disable the implicit filtering of zero values,282you can use the `allow_zero_values` option in the [options section](#options_section_syntax).283284### Hop window285286By 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 correlated289within each hop window.290291For example, for a rule that is run over the time range [1:00, 2:00], with a292`match` section over `30m`, a possible set of overlapping hop windows293that 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.295296### Sliding window297298Using hop windows is not an effective way to search for events that happen in a specific order (for example, `e1` happens up to 2299minutes 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.301302A 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 when304beginning or ending with a specified pivot event variable. Events are then305correlated within each sliding window. This makes it possible to search for306events that happen in a specific order (for example, `e1` happens within 2307minutes of `e2`). An occurrence of event `e1` and an occurrence of event `e2`308are correlated if event `e1` occurs within the sliding window duration after309event `e2`.310311Specify sliding windows in the `match` section of a rule as follows:312313`<match-var-1>, <match-var-2>, ... over <duration> before|after <pivot-event-var>`314315The pivot event variable is the event variable that sliding windows are based316on. If you use the `before` keyword, sliding windows are generated, ending with317each occurrence of the pivot event. If the `after` keyword is used, sliding318windows are generated beginning with each occurrence of the pivot event.319320The following are examples of valid sliding window usages:321322* `$var1, $var2 over 5m after $e1`323* `$user over 1h before $e2`324325See [a sliding window rule example](/chronicle/docs/detection/yara-l-2-0-overview#sliding_window_rule_example).326327**Note:** Using sliding windows instead of hop windows has been known to result in328slower performance. We recommend using sliding windows only for329specific cases, such as when event order is absolutely necessary or when330searching for the non-existence of events.331332We recommend not using sliding windows for single-event rules, because333sliding windows are designed to detect multiple events. If one of334your rules falls in this category, We recommend one of335the following workarounds:336337* Convert the rule to use multiple event variables, and update the condition338 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.342343## Outcome section syntax344345In the `outcome` section, you can define up to 20 outcome variables, with346arbitrary names. These outcomes will be stored in the detections generated by347the rule. Each detection may have different values for the outcomes.348349The outcome name, `$risk_score`, is special. You can optionally define an350outcome with this name, and if you do, it must be an integer or float type. If populated,351the `risk_score` will be shown in the352[Enterprise Insights view](https://cloud.google.com/chronicle/docs/investigation/view-alerts-insights.md) for353alerts that come from rule detections.354355If you don't include a `$risk_score` variable in the outcome section of a rule,356one of the following default values is set:357358* 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.360361The value of `$risk_score` is stored in the `security_result.risk_score` UDM field.362363### Outcome variable data types364365Each outcome variable can have a different data type, which is determined by the expression366used to compute it. We support the following outcome data types:367368* integer369* floats370* string371* lists of integers372* lists of floats373* lists of strings374375### Conditional logic376377You can use conditional logic to compute the value of an outcome. Conditionals378are specified using the following syntax pattern:379380```381if(BOOL_CLAUSE, THEN_CLAUSE)382if(BOOL_CLAUSE, THEN_CLAUSE, ELSE_CLAUSE)383384```385386You can read a conditional expression as "if BOOL\_CLAUSE is true, then return387THEN\_CLAUSE, else return ELSE\_CLAUSE".388389BOOL\_CLAUSE must evaluate to a boolean value. A BOOL\_CLAUSE expression takes a390similar form as expressions in the `events` section. For example, it can391contain:392393* UDM field names with comparison operator, for example:394395 `if($context.graph.entity.user.title = "Vendor", 100, 0)`396* placeholder variable that was defined in the `events` section, for example:397398 `if($severity = "HIGH", 100, 0)`399* another outcome variable defined in the `outcome` section, for example:400401 `if($risk_score > 20, "HIGH", "LOW")`402* functions that return a boolean, for example:403404 `if(re.regex($e.network.email.from, `.*altostrat.com`), 100, 0)`405* look up in a [reference list](#reference_lists_syntax), for example:406407 `if($u.principal.hostname in %my_reference_list_name, 100, 0)`408* aggregation comparison, for example:409410 `if(count($login.metadata.event_timestamp.seconds) > 5, 100, 0)`411412The THEN\_CLAUSE and ELSE\_CLAUSE must be the same data type. We support integers, floats, and strings.413414You can omit the ELSE\_CLAUSE if the data type is integer or a float. If omitted, the415ELSE\_CLAUSE evaluates to 0. For example:416417```418`if($e.field = "a", 5)` is equivalent to `if($e.field = "a", 5, 0)`419420```421422You must provide the ELSE\_CLAUSE if the data type is string or if the THEN\_CLAUSE423is a placeholder variable or outcome variable.424425### Mathematical operations426427You 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.428429The following snippet is an example computation in the `outcome` section:430431```432outcome:433 $risk_score = max(100 + if($severity = "HIGH", 10, 5) - if($severity = "LOW", 20, 0))434435```436437Mathematical operations are allowed on the following types of operands as long as438each operand and the entire arithmetic expression is properly aggregated (See [Aggregations](#aggregations)):439440* Numeric event fields441* Numeric placeholder variables defined in the `events` section442* Numeric outcome variables defined in the `outcome` section443* Functions returning ints or floats444* Aggregations returning ints or floats445446Modulus is not allowed on floats.447448### Placeholder variables in outcomes449450When computing outcome variables, you can use placeholder variables which were451defined in the events section of your rule. In this example, assume that452`$email_sent_bytes` was defined in the events section of the rule:453454Single-event example:455456```457// No match section, so this is a single-event rule.458459outcome:460 // Use placeholder directly as an outcome value.461 $my_outcome = $email_sent_bytes462463 // Use placeholder in a conditional.464 $other_outcome = if($file_size > 1024, "SEVERE", "MODERATE")465466condition:467 $e468469```470471Multi-event example:472473```474match:475 // This is a multi event rule with a match section.476 $hostname over 5m477478outcome:479 // Use placeholder directly in an aggregation function.480 $max_email_size = max($email_sent_bytes)481482 // Use placeholder in a mathematical computation.483 $total_bytes_exfiltrated = sum(484 1024485 + $email_sent_bytes486 + $file_event.principal.file.size487 )488489condition:490 $email_event and $file_event491492```493494### Outcome variables in outcome assignment expressions495496Outcome variables can be used to derive other outcome variables, similar to497placeholder variables defined in the `events` section. You can refer to an outcome498variable in the assignment of another outcome variable with a `$` token followed499by the variable name. Outcome variables must be defined before they can be referenced500in the rule text. When used in an assignment expression, outcome variables must501not be aggregated (See [Aggregations](#aggregations)).502503In the following example, the outcome variable `$risk_score` derives its504value from the outcome variable `$event_count`:505506Multi-event example:507508```509match:510 // This is a multi event rule with a match section.511 $hostname over 5m512513outcome:514 // Aggregates all timestamp on login events in the 5 minute match window.515 $event_count = count($login.metadata.event_timestamp.seconds)516517 // $event_count cannot be aggregated again.518 $risk_score = if($event_count > 5, "SEVERE", "MODERATE")519520 // This is the equivalent of the 2 outcomes above combined.521 $risk_score2 = if(count($login.metadata.event_timestamp.seconds) > 5, "SEVERE", "MODERATE")522523condition:524 $e525526```527528Outcome variables can be used in any type of expression on the right-hand-side of an outcome assignment,529except in the following expressions:530531* Aggregations532* `Arrays.length()` function calls533* With `any` or `all` modifiers534535### Aggregations536537Repeated event fields are non-scalar values. That is, a single variable points to538multiple values. For example, the event field variable `$e.target.ip` is a repeated field539and can have zero, one, or many ip values. It is a non-scalar value. Whereas the event field variable540`$e.principal.hostname` is not a repeated field and only has 1 value (i.e. a scalar value).541542Similarly, both non-repeated event fields and repeated event fields used in the outcome section543of a rule with a match window are non-scalar values. For example, the following rule groups events544using a match section and refers to a non-repeated event field in the outcome section:545546```547rule OutcomeAndMatchWindow{548 ...549 match:550 $userid over 5m551 outcome:552 $hostnames = array($e.principal.hostname)553 ...554}555556```557558Any 5-minute window the rule executes over might contain zero, one, or many events. The outcome section559operates on all events in a match window. Any event field variable referred to within the560outcome 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 variable563`$e.principal.hostname` is treated as a non-scalar value in the `outcome` section of this rule.564565Because outcome variables must always yield a single scalar value, any non-scalar value which566an 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:568569* Event fields (repeated or non-repeated) when the rule uses a match section570* Event placeholders (repeated or non-repeated) when the rule uses a match section571* Repeated event fields when the rule does not use a match section572* Repeated event placeholders when the rule does not use a match section573574Scalar event fields, scalar event placeholders, and constants can be wrapped in575aggregation functions in rules that don't include a match section. However, in576most cases, these aggregations return the wrapped value, making them unnecessary.577An exception is the `array()` aggregation, which you can use to explicitly convert578a scalar value into an array.579580Outcome variables are treated like aggregations: they must not be re-aggregated581when referred to in another outcome assignment.582583You can use the following aggregation functions:584585* `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 of589 possible values.590* `count()`: behaves like `count_distinct()`, but returns a non-distinct count of591 possible values.592* `array_distinct()`: collects all possible distinct values, then outputs a list of these values. It593 will truncate the list of distinct values to 25 random elements. The deduplication594 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 of596 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 of598 the listed value occurred.599* `period_start_for_min()`: start of the time period where the minimum of600 the listed value occurred.601602The aggregate function is important when a rule includes a `condition` section603that specifies multiple events must exist, because the aggregate function will604operate on all the events that generated the detection.605606For example, if your `outcome` and `condition` sections contain:607608```609outcome:610 $asset_id_count = count($event.principal.asset_id)611 $asset_id_distinct_count = count_distinct($event.principal.asset_id)612613 $asset_id_list = array($event.principal.asset_id)614 $asset_id_distinct_list = array_distinct($event.principal.asset_id)615616condition:617 #event > 1618619```620621Since the condition section requires there to be more than one `event` for each622detection, the aggregate functions will operate on multiple events. Suppose the623following events generated one detection:624625```626event:627 // UDM event 1628 asset_id="asset-a"629630event:631 // UDM event 2632 asset_id="asset-b"633634event:635 // UDM event 3636 asset_id="asset-b"637638```639640Then the values of your outcomes will be:641642* $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"]`646647#### Things to know when using the outcome section:648649Other notes and restrictions:650651* The `outcome` section cannot reference a new placeholder variable which652 wasn't already defined in the `events` section or in the `outcome` section.653* The `outcome` section cannot use event variables that have not654 been defined in the `events` section.655* The `outcome` section can use an event field that was not656 used in the `events` section, given that the event variable that the event657 field belongs to was already defined in the `events` section.658* The `outcome` section can only correlate event variables that have already659 been correlated in the `events` section. Correlations happen when two660 event fields from different event variables are equated.661662You can find an example using the outcome section in663[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 detection665deduping with the outcome section.666667## Condition section syntax668669* 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.671672### Count character673674The `#` character is a special character in the `condition` section. If it is675used before any event or placeholder variable name, it represents the number of676distinct events or values that satisfy all of the `events` section conditions.677678For example, `#c > 1` means the variable `c` must occur more than 1 time.679680### Value character681682The `$` character is a special character in the `condition` section. If it is683used before any outcome variable name, it represents the value of that outcome.684685If it is used before any event or placeholder variable name (for example,686`$event`), it represents `#event > 0`.687688### Event and placeholder conditionals689690List condition predicates for events and placeholder variables here, joined691with the keyword `and` or `or`. The keyword `and` can be used between any692conditions, but the keyword `or` can only be used when the rule only has a693single event variable.694695A valid example of using `or` between two placeholders on the same event:696697```698rule ValidConditionOr {699 meta:700 events:701 $e.metadata.event_type = "NETWORK_CONNECTION"702703 // 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.707708 match:709 $ph over 5m710711 condition:712 $ph2 or $ph3713}714715```716717An invalid example of using `or` between two conditions on different events:718719```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.hostname726727 $ph = $e.principal.user.userid // Define a placeholder variable to put in match section.728729 match:730 $ph over 5m731732 condition:733 $e or $e2 // This line will cause an error because there is an or between events.734}735736```737738**Note:** Don't use the keyword `not` in event and placeholder conditionals.739740### Bounded and Unbounded conditions741742The following conditions are bounded conditions. They force the associated743event variable to exist, meaning that at least one occurrence of the event must744appear in any detection.745746* `$var // equivalent to #var > 0`747* `#var > n // where n >= 0`748* `#var >= m // where m > 0`749750The following conditions are unbounded conditions. They allow the associated751event variable to not exist, meaning that it is possible that no occurrence of752the event appears in a detection and any reference to fields on the event753variable will yield a zero value. Unbounded conditions can be used to detect754the absence of an event over a period of time. For example, a threat event755without a mitigation event within a 10 minute window. Rules using unbounded756conditions are called non-existence rules.757758* `!$var // equivalent to #var = 0`759* `#var >= 0`760* `#var < n // where n > 0`761* `#var <= m // where m >= 0`762763**Note:** For non-existence rules, the detection engine adds a 1 hour delay to the764expected latency (based on the rule's run frequency) to allow for late-arriving765data.766767#### Requirements for non-existence768769For a rule with non-existence to compile, it must satisfy the following requirements:7707711. 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 with773 at least one bounded UDM event.7743. If an entity has an unbounded condition, it must be associated with at775 least one bounded UDM event.776777Consider the following rule with the condition section omitted:778779```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.787788 $user = $u1.principal.user.userid // Match variable is required for Multi-Event Rule.789790 // Placeholder Associations:791 // u1 u2792 // | \ /793 // port ip794 // | \795 // e1 e2796 $u1.target.port = $port797 $e1.graph.entity.port = $port798 $u1.principal.ip = $ip799 $u2.target.ip = $ip800 $e2.graph.entity.ip = $ip801802 // UDM-Entity Associations:803 // u1 - u2804 // | \ |805 // e1 e2806 $u1.metadata.event_type = $u2.metadata.event_type807 $e1.graph.entity.hostname = $u1.principal.hostname808 $e2.graph.entity.hostname = $u1.target.hostname809 $e2.graph.entity.hostname = $u2.principal.hostname810811 match:812 $user over 5m813814 condition:815 <condition_section>816}817818```819820The following are *valid* examples for the `<condition_section>`:821822* `$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.830831The following are *invalid* examples for the `<condition_section>`:832833* `$u1 and $e1`834 + Every UDM event and entity appearing in the Events Section must appear in835 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.848849**Note:** Don't use a `match` variable in the `condition` section. It is a semantic850error 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.851852### Outcome conditionals853854List condition predicates for outcome variables here, joined with the keyword `and` or `or`, or preceded by the keyword `not`.855856Specify outcome conditionals differently depending on the type of the outcome variable:857858* **integer**: compare against an integer literal with operators `=, >, >=, <, <=, !=`, for example:859860 `$risk_score > 10`861* **float**: compare against a float literal with operators `=, >, >=, <, <=, !=`, for example:862863 `$risk_score <= 5.5`864* **string**: compare against a string literal with either `=` or `!=`, for example:865866 `$severity = "HIGH"`867* **list of integers or arrays**: specify condition using the `arrays.contains` function, for example:868869 `arrays.contains($event_ids, "id_1234")`870871**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`.873874#### Rule classification875876Specifying 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.878879## Options section syntax880881In the `options` section, you can specify the options for the rule. Here is882an example of how to specify the options section:883884```885rule RuleOptionsExample {886 // Other rule sections887888 options:889 allow_zero_values = true890}891892```893894You can specify options using the syntax `key = value`, where `key` must be a895predefined option name and `value` must be a valid value for the option, as896specified for the following options:897898### allow\_zero\_values899900The valid values for this option are `true` and `false`, which determine901if this option is enabled or not. The default value is `false`. This option is902disabled if it is not specified in the rule.903904To enable this setting, add the following905to the options section of your rule: `allow_zero_values = true`. Doing so906will prevent the rule from implicitly filtering out the907zero values of placeholders that are used in the match section, as908described in [zero value handling in the match section](#zero_value_handling_in_the_match_section).909910### suppression\_window911912The `suppression_window` option lets you control how often a rule triggers a913detection. It prevents the same rule from generating multiple detections within914a specified time window, even if the rule's conditions are met multiple times.915Suppression windowing uses a tumbling window approach, which suppresses916duplicates over a fixed-size, non-overlapping window.917918You can optionally provide a `suppression_key` to further refine which instances919of the rule are suppressed within the suppression window. If not specified, all920instances of the rule are suppressed. This key is defined as an outcome variable.921922In the following example, `suppression_window` is set to `5m` and `suppression_key` is923set to the `$hostname` variable. After the rule triggers a detection for924`$hostname`, any further detections for `$hostname` are suppressed for the next925five minutes. However, if the rule triggers on an event with a different hostname,926a detection is created.927928The default value of `suppression_window` is `0`; that is, the suppression929window 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.931932Example:933934```935rule SuppressionWindowExample {936 // Other rule sections937938 outcome:939 $suppression_key = $hostname940941 options:942 suppression_window = 5m943}944945```946947## Composite detection rules948949**Note:** This feature is covered by [Pre-GA Offerings Terms](https://chronicle.security/legal/service-terms/) of the Google Security Operations Service950Specific 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/).953954Composite detection in Google SecOps involves connecting multiple955YARA-L rules. This sections explains how to build a956composite rule. For an overview of composite detections,957see [Overview of composite detections](/chronicle/docs/detection/composite-detections).958959### Rule structure960961Composite detection rules are always multi-event rules and follow the same962[structure and syntax](/chronicle/docs/detection/yara-l-2-0-syntax#rule_structure).963The following requirements apply to composite detection rules:964965* 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 these967 data sources.968969For information on rule limitations, see [Limitations](/chronicle/docs/detection/composite-detections#limitations).970971### Use detections as input to rules972973Composite rules can reference rule detections generated by any custom or curated rule.974Google SecOps provides two methods for doing this.975976#### Reference detection content using outcome variables, match variables, or meta labels977978To access data from a detection without referencing the original UDM events,979use `outcome` variables, `match` variables, or `meta` labels. We recommend this980approach because it provides greater flexibility and better compatibility across981different rule types.982983For example, multiple rules can store a string (such as a URL, filename, or984registry key) in a common `outcome` variable if you're looking for that string985across different contexts. To access this string from a composite rule, start986with `detection` and locate the relevant information using elements from the987[Collection resource](/chronicle/docs/reference/rest/v1alpha/Collection).988989**Example:**990For example, suppose a detection rule produces the following information:991992* Outcome variable: `dest_domain = "cymbal.com"`993* UDM field: `target.hostname = "cymbal.com"`994995In the composite rule, you can access this data using the following paths:996997* `detection.detection.outcomes["dest_domain"]` to access the `dest_domain`998 outcome variable.999* `detection.collection_elements.references.event.target.hostname` to access1000 the `target.hostname` UDM field.1001* `detection.time_window.start_time.seconds` to access the detection timestamp.10021003The Collection API and the `SecurityResult` API provide access to both:10041005* Detection metadata and outcome values (`detection.detection`)1006* Underlying UDM events from referenced rules (`collection_elements`)10071008#### Reference detection content using rule ID or rule name10091010You can reference a rule by either its name or ID. We recommend this1011approach when your detection logic depends on specific rules. Referencing1012relevant rules by name or ID improves performance and prevents timeouts by1013reducing the data analyzed. For example, you can directly query fields like1014`target.url` or `principal.ip` from a known previous detection.10151016* **Reference a rule by rule ID (recommended):** use the1017 `detection.detection.rule_id` field to reference a rule by ID. You can find the1018 rule ID in the rule's URL in Google SecOps. User-generated rules1019 have IDs in the format `ru_UUID`, while curated detections have IDs in the1020 format `ur_UUID`. For example:10211022 `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 a1025 regular expression to match it. For example:10261027 + `detection.detection.rule_name = "My Rule Name"`1028 + `detection.detection.rule_name = "/PartOfName/"`10291030**Note:** We recommend using rule IDs for referencing because IDs are unique and1031don't change. Rule names can be modified, which could potentially break your1032composite detection.10331034### Combine events and detections10351036Composite rules can combine different data sources, including UDM events, entity1037graph data, and detection fields. The following guidelines apply:10381039* **Use distinct variables per source**—Assign unique event variables to each data source (for example, `$e` for1040 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, or1043 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.10451046For example:10471048```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 = $domain1055 $d.detection.collection_elements.references.event.principal.asset.hostname = $hostname10561057 $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, "([^.]*)")10611062 $prevalence.graph.metadata.entity_type = "DOMAIN_NAME"1063 $prevalence.graph.metadata.source_type = "DERIVED_CONTEXT"1064 $prevalence.graph.entity.hostname = $domain1065 $prevalence.graph.entity.domain.prevalence.day_count = 101066 $prevalence.graph.entity.domain.prevalence.rolling_max <= 51067 $prevalence.graph.entity.domain.prevalence.rolling_max > 010681069 match:1070 $hostname over 1h10711072 outcome:1073 $risk_score = 801074 $CL_target = array($domain)10751076 condition:1077 $e and $d and $prevalence1078}10791080```10811082### Create sequential composite detections10831084Sequential composite detections identify patterns of related events where the1085sequence of detections is important, such as a brute-force login attempt1086detection, followed by a successful login. These patterns can combine multiple1087base detections, raw UDM events, or both.10881089To create a sequential composite detection, you must enforce that order within1090your rule. To enforce the expected sequence, use one of the following methods:10911092* **Sliding windows:** Define the sequence of detections using sliding windows1093 in your `match` conditions.1094* **Timestamp comparisons:** Compare the timestamps of detections within your1095 rule logic to ensure that they happen in the selected order.10961097For example:10981099```1100events:1101 $d1.detection.detection.rule_name = "fileEvent_rule"1102 $userid = $d1.detection.detection.outcomes["user"]1103 $hostname = $d1.detection.detection.outcomes["hostname"]11041105 $d2.detection.detection.rule_name = "processExecution_rule"1106 $userid = $d2.detection.detection.outcomes["user"]1107 $hostname = $d2.detection.detection.outcomes["hostname"]11081109 $d3.detection.detection.rule_name = "networkEvent_rule"1110 $userid = $d3.detection.detection.outcomes["user"]1111 $hostname = $d3.detection.detection.outcomes["hostname"]11121113$d3.detection.collection_elements.references.event.metadata.event_timestamp.seconds > $d2.detection.collection_elements.references.event.metadata.event_timestamp.seconds11141115 match:1116 $userid over 24h after $d111171118```11191120## Boolean expressions11211122Boolean expressions are expressions with a boolean type.11231124### Comparisons11251126For a binary expression to use as condition, use the following syntax:11271128* `<EXPR> <OP> <EXPR>`11291130Expression can be either event field, variable, literal, or function expression.11311132For example:11331134* `$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")`11431144If both sides are literals, it is regarded as a compilation error.11451146### Functions11471148Some function expressions return boolean value, which can be used as an individual predicate in the `events` section. Such functions are:11491150* `re.regex()`1151* `net.ip_in_range_cidr()`11521153For example:11541155* `re.regex($e.principal.hostname, `.*\.google\.com`)`1156* `net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/24")`11571158### Reference list expressions11591160You can use reference lists in the events section. See the section on1161[Reference Lists](#reference_lists_syntax) for more details.11621163### Logical expressions11641165You can use the logical `and` and logical `or` operators in the `events` section as shown in the following examples:11661167* `$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"`11701171By default, the precedence order from highest to lowest is `not`, `and`, `or`.11721173For 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.11741175In the `events` section, predicates are joined using the `and` operator if an operator is not explicitly defined.11761177The order of evaluation may be different if the `and` operator is implied in the expression.11781179For example, consider the following comparison expressions where `or` is defined explicitly. The `and` operator is implied.11801181```1182$e1.field = "bat"1183or $e1.field = "baz"1184$e2.field = "bar"11851186```11871188This example is interpreted as follows:11891190```1191($e1.field = "bat" or $e1.field = "baz")1192and ($e2.field = "bar")11931194```11951196Because `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.11981199**Note:** There is a limit on the number of `and` and `or` values you can specify for a1200single rule. This limit varies depending on the complexity of the rule and the1201complexity of the data in your Google SecOps account. Contact your Google SecOps representative for information on alternatives to this type of1202rule.12031204## Enumerated types12051206You 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.12071208In the following example, 'USER\_UNCATEGORIZED' and 'USER\_RESOURCE\_DELETION' correspond to 15000 and 15014, so the rule will look for all the listed events:12091210```1211$e.metadata.event_type >= "USER_CATEGORIZED" and $e.metadata.event_type <= "USER_RESOURCE_DELETION"12121213```12141215List of events:12161217* USER\_RESOURCE\_DELETION1218* USER\_RESOURCE\_UPDATE\_CONTENT1219* USER\_RESOURCE\_UPDATE\_PERMISSIONS1220* USER\_STATS1221* USER\_UNCATEGORIZED12221223## Nocase Modifier12241225When 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.12261227* `$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`12311232This cannot be used when a type of field is an enumerated value. The following1233examples are invalid and will generate compilation errors:12341235* `$e.metadata.event_type = "NETWORK_DNS" nocase`1236* `$e.network.ip_protocol = "TCP" nocase`12371238## Repeated fields12391240In the Unified Data Model (UDM), some fields are labeled as repeated, which indicates1241that they are lists of values or other types of messages.12421243### Repeated fields and boolean expressions12441245There are 2 kinds of boolean expressions that act on repeated fields:124612471. Modified12482. Unmodified12491250Consider the following event:12511252```1253event_original {1254 principal {1255 // ip is a repeated field1256 ip: [ "192.0.2.1", "192.0.2.2", "192.0.2.3" ]12571258 hostname: "host"1259 }1260}12611262```12631264#### Modified expressions12651266The following sections describe the purpose and how to use the `any` and `all` modifiers in expressions.12671268##### any12691270If *any* element of the repeated field satisfies the condition, the event as a whole satisfies the condition.12711272* `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`.12741275##### all12761277If *all* elements of the repeated field satisfy the condition, the event as a whole satisfies the condition.12781279* `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"`.12811282**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.12831284When writing a condition with `any` or `all`, be aware that negating the condition1285with `not` might not have the same meaning as using the negated operator.12861287For example:12881289* `not all $e.principal.ip = "192.168.12.16"` checks if not all IP addresses1290 match `192.168.12.16`, meaning the rule is checking whether at least one IP address1291 does not match `192.168.12.16`.1292* `all $e.principal.ip != "192.168.12.16"` checks if all IP addresses don't match1293 `192.168.12.16`, meaning the rule is checking that no IP addresses match to `192.168.12.16`.12941295Constraints:12961297* `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.13001301#### Unmodified expressions13021303With 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.13041305The rule is applied on the following copies:13061307| 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" |13121313If *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.13141315The following rule returns one match when run against the `event_original` example1316dataset, because `event_copy_1` satisfies all of the events predicates:13171318```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.x1323 $e.principal.ip = "192.0.2.1"1324 condition:1325 $e1326}13271328```13291330The 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` that1332satisfies *all* the event predicates.13331334```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 $e1342}13431344```13451346Modified 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:13471348```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 $e1356}13571358```13591360The rule is applied on the following copies:13611362| 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"] |13671368In 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.13691370Another way to think about these expression types are:13711372* 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.13741375### Repeated fields and placeholders13761377Repeated 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.13781379The following example generates one match. The `$ip` placeholder is equal1380to `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`.13821383```1384// Generates 1 match.1385rule repeated_field_placeholder1 {1386 meta:1387 events:1388 $ip = $e.principal.ip1389 $ip = "192.0.2.1"1390 $host = $e.principal.hostname13911392 match:1393 $host over 5m13941395 condition:1396 $e1397}13981399```14001401The following example generates three matches. The `$ip` placeholder is equal1402to 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 matches1404where each match has a different value for the `$ip` match variable. Each match has the same1405event sample: a single element, `event_original`.14061407```1408// Generates 3 matches.1409rule repeated_field_placeholder2 {1410 meta:1411 events:1412 $ip = $e.principal.ip1413 net.ip_in_range_cidr($ip, "192.0.2.0/8") // Checks if IP matches 192.x.x.x14141415 match:1416 $ip over 5m14171418 condition:1419 $e1420}14211422```14231424**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.14251426#### Outcomes using placeholders assigned to repeated fields14271428Placeholders 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.14291430Consider the following rule:14311432```1433rule outcome_repeated_field_placeholder {1434 meta:1435 events:1436 $ip = $e.principal.ip1437 $ip = "192.0.2.1" or $ip = "192.0.2.2"1438 $host = $e.principal.hostname14391440 match:1441 $host over 5m14421443 outcome:1444 $o = array_distinct($ip)14451446 condition:1447 $e1448}14491450```14511452There are 4 stages of execution for this rule. The first stage is event copying:14531454| 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 |14591460The events section will then filter out rows that don't match the filters:14611462| 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 |14661467`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"`.14681469The match section will then group by match variables and the outcome section will perform aggregation on each group:14701471| $host | $o | $e |1472| --- | --- | --- |1473| "host" | ["192.0.2.1", "192.0.2.2"] | event\_id |14741475`$o = array_distinct($ip)` is calculated using `$ip` from the previous stage and not the event copying stage.14761477Finally, 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.14781479`$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`.14801481### Array indexing14821483You 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.14841485* `$e.principal.ip[0] = "192.168.12.16"`1486* `$e.principal.ip[999] = ""` If there are fewer than 1000 elements, this evaluates to `true`.14871488Constraints:14891490* 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`.14951496### Repeated messages14971498When 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.14991500Consider the following event:15011502```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" ]15081509 hostname: "alice"1510 }1511 about {1512 hostname: "bob"1513 }1514}15151516```15171518As 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:15191520```1521rule repeated_message_1 {1522 meta:1523 events:1524 $e.about.ip = "192.0.2.1"1525 $e.about.hostname = "bob"1526 condition:1527 $e1528}15291530```15311532The rule is applied on the following copies:15331534| 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" |15401541The event does not match on the rule because there exists no event copy that satisfies all of the expressions.15421543#### Repeated messages and array indexing15441545Another unexpected behavior can occur when using array indexing with unmodified expressions on repeated message fields. Consider the following example rule which uses array indexing:15461547```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 $e1555}15561557```15581559The rule is applied to the following copies:15601561| 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" |15671568Since `event_copy_1` satisfies all of the expressions in `repeated_message_2`, the event matches on the rule.15691570This 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.15711572## Comments15731574Designate comments with two slash characters (`// comment`) or multi-line comments set off using slash asterisk characters (`/* comment */`), as you would in C.15751576## Literals15771578Nonnegative integers and floats, string, boolean, and regular expression literals are supported.15791580### String and regular expression literals15811582You 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.158315841. Double quotes (") — Use for normal strings. Must include escape characters.1585 For example: "hello\tworld" —\t is interpreted as a tab15862. Back quotes (`) — Use to interpret all characters literally.1587 For example: `hello\tworld` —\t is not interpreted as a tab15881589For regular expressions, you have two options.15901591If you want to use regular expressions directly without the `re.regex()` function, use `/regex/` for the regular expression literals.15921593You 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.15941595For example, the following regular expressions are equivalent:15961597* `re.regex($e.network.email.from, `.*altostrat\.com`)`1598* `re.regex($e.network.email.from, ".*altostrat\\.com")`1599* `$e.network.email.from = /.*altostrat\.com/`16001601Google recommends using back quote characters for strings in regular expressions for ease of readability.16021603## Operators16041605You can use the following operators in YARA-L:16061607| | |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 |16161617## Variables16181619In YARA-L 2.0, all variables are represented as `$<variable name>`.16201621You can define the following types of variables:16221623* 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.16261627**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*16281629Use 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).16301631## Keywords16321633Keywords in YARA-L 2.0 are case-insensitive. For example, `and` or `AND` are1634equivalent. Variable names must not conflict with keywords. For example,1635`$AND` or `$outcome` is invalid.16361637The 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`.16381639### Maps16401641YARA-L supports map access for Structs and Labels.16421643#### Structs and Labels16441645Some 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.16461647To search for a specific key-value pair in both Struct and Label, use the standard map syntax:16481649```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"16541655```16561657The map access always returns a string.16581659#### Supported cases16601661##### Events and Outcome Section16621663```1664// Using a Struct field in the events section1665events:1666 $e.udm.additional.fields["pod_name"] = "kube-scheduler"16671668// Using a Label field in the outcome section1669outcome:1670 $value = array_distinct($e.metadata.ingestion_labels["MetadataKeyDeletion"])16711672```16731674##### Assigning a map value to a Placeholder16751676```1677$placeholder = $u1.metadata.ingestion_labels["MetadataKeyDeletion"]16781679```16801681##### Using a map field in a join condition16821683```1684// using a Struct field in a join condition between two udm events $u1 and $u21685$u1.metadata.event_type = $u2.udm.additional.fields["pod_name"]16861687```16881689#### Unsupported cases16901691Maps are not supported in the following cases.16921693##### Combining `any` or `all` keywords with a map16941695For example, the following is not supported:16961697```1698all $e.udm.additional.fields["pod_name"] = "kube-scheduler"16991700```17011702##### Other types of values17031704The map syntax can only return a string value. In the case of1705[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.17081709#### Duplicate value handling17101711Map accesses always returns a single value. In the uncommon1712edge case that the map access could refer to multiple values, the map1713access will deterministically return the first value.17141715This can happen in either of the following cases:17161717* A label has a duplicate key.17181719 The label structure represents a map, but does not enforce key uniqueness.1720 By convention, a map should have unique keys, so Google SecOps does1721 not recommend populating a label with duplicate keys.17221723 The rule text `$e.metadata.ingestion_labels["dupe-key"]` would return1724 the first possible value, `val1`, if run over the following data example:17251726```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 }17401741```1742* A label has an ancestor repeated field.17431744 A repeated field might contain a label as a child field. Two different1745 entries in the top-level repeated field might contain labels that1746 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 following1748 data example:17491750```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 }17681769```17701771## Functions17721773This section describes the YARA-L 2.0 functions that you can use in detection1774engine rules and search.17751776**Note:** The use of the event variable `$e` is optional when YARA-L is used in1777search. Both `principal.hostname` and `$e.principal.hostname` are supported in1778search.17791780These functions can be used in the following parts of a YARA-L rule:17811782* `events` section.1783* `BOOL_CLAUSE` of a conditional in the [outcome section](#outcome_section_syntax).17841785### arrays.concat17861787Supported in:17881789[Rules](/chronicle/docs/detection/default-rules)1790[Search](/chronicle/docs/investigation/udm-search)17911792```1793arrays.concat(string_array, string_array)17941795```17961797#### Description17981799Returns a new string array by copying elements from original string arrays.18001801#### Param data types18021803`ARRAY_STRINGS`, `ARRAY_STRINGS`18041805#### Return type18061807`ARRAY_STRINGS`18081809#### Code samples18101811##### Example 118121813The following example concatenates two different string arrays.18141815```1816arrays.concat(["test1", "test2"], ["test3"]) = ["test1", "test2", "test3"]18171818```18191820##### Example 218211822The following example concatenates arrays with empty string.18231824```1825arrays.concat([""], [""]) = ["", ""]18261827```18281829##### Example 318301831The following example concatenates empty arrays.18321833```1834arrays.concat([], []) = []18351836```1837183818391840### arrays.join\_string18411842Supported in:18431844[Rules](/chronicle/docs/detection/default-rules)1845[Search](/chronicle/docs/investigation/udm-search)18461847```1848arrays.join_string(array_of_strings, optional_delimiter)18491850```18511852#### Description18531854Converts an array of strings into a single string separated by the optional parameter. If no delimiter is provided, the empty string is used.18551856#### Param data types18571858`ARRAY_STRINGS`, `STRING`18591860#### Return type18611862`STRING`18631864#### Code samples18651866Here are some examples of how to use the function:18671868##### Example 118691870This example joins an array with non-null elements and a delimiter.18711872```1873arrays.join_string(["foo", "bar"], ",") = "foo,bar"18741875```18761877##### Example 218781879This example joins an array with a null element and a delimiter.18801881```1882arrays.join_string(["foo", NULL, "bar"], ",") = "foo,bar"18831884```18851886##### Example 318871888This example joins an array with non-null elements and no delimiter.18891890```1891arrays.join_string(["foo", "bar"]) = "foobar"18921893```1894189518961897### arrays.length18981899Supported in:19001901[Rules](/chronicle/docs/detection/default-rules)1902[Search](/chronicle/docs/investigation/udm-search)19031904```1905arrays.length(repeatedField)19061907```19081909#### Description19101911Returns the number of repeated field elements.19121913#### Param data types19141915`LIST`19161917#### Return type19181919`NUMBER`19201921#### Code samples19221923##### Example 119241925Returns the number of repeated field elements.19261927```1928arrays.length($e.principal.ip) = 219291930```19311932##### Example 219331934If multiple repeated fields are along the path, returns the total number of repeated field elements.19351936```1937arrays.length($e.intermediary.ip) = 319381939```1940194119421943### arrays.max19441945Supported in:19461947[Rules](/chronicle/docs/detection/default-rules)1948[Search](/chronicle/docs/investigation/udm-search)19491950```1951arrays.max(array_of_ints_or_floats)19521953```19541955#### Description19561957Returns the greatest element in an array or zero if the array is empty.19581959#### Param data types19601961`ARRAY_INTS|ARRAY_FLOATS`19621963#### Return type19641965`FLOAT`19661967#### Code samples19681969Here are some examples of how to use the function:19701971##### Example 119721973This example returns the greater element in an array of integers.19741975```1976arrays.max([10, 20]) = 20.00000019771978```19791980##### Example 219811982This example returns the greater element in an array of floats.19831984```1985arrays.max([10.000000, 20.000000]) = 20.00000019861987```1988198919901991### arrays.min19921993Supported in:19941995[Rules](/chronicle/docs/detection/default-rules)1996[Search](/chronicle/docs/investigation/udm-search)19971998```1999arrays.min(array_of_ints_or_floats[, ignore_zeros=false])20002001```20022003#### Description20042005Returns the smallest element in an array or zero if the array is empty. If the2006second, optional argument is set to true, elements equal to zero are ignored.20072008#### Param data types20092010`ARRAY_INTS|ARRAY_FLOATS`, `BOOL`20112012#### Return type20132014`FLOAT`20152016#### Code samples20172018Here are some examples of how to use the function:20192020##### Example 120212022This example returns the smallest element in an array of integers.20232024```2025arrays.min([10, 20]) = 10.00000020262027```20282029##### Example 220302031This example returns the smallest element in an array of floats.20322033```2034arrays.min([10.000000, 20.000000]) = 10.00000020352036```20372038##### Example 320392040This example returns the smallest element in an array of floats, while ignoring the zeroes.20412042```2043arrays.min([10.000000, 20.000000, 0.0], true) = 10.00000020442045```2046204720482049### arrays.size20502051Supported in:20522053[Rules](/chronicle/docs/detection/default-rules)2054[Search](/chronicle/docs/investigation/udm-search)20552056```2057arrays.size( array )20582059```20602061#### Description20622063Returns the size of the array. Returns 0 for an empty array.20642065#### Param data types20662067`ARRAY_STRINGS|ARRAY_INTS|ARRAY_FLOATS`20682069#### Return type20702071`INT`20722073#### Code samples20742075##### Example 120762077This example uses a string array that contains two elements.20782079```2080arrays.size(["test1", "test2"]) = 220812082```20832084##### Example 220852086This example uses an int array that contains 3 elements.20872088```2089arrays.size([1, 2, 3]) = 320902091```20922093##### Example 320942095This example uses a float array thats contains 1 elements20962097```2098arrays.size([1.200000]) = 120992100```21012102##### Example 421032104This example uses an empty array.21052106```2107arrays.size([]) = 021082109```2110211121122113### arrays.index\_to\_float21142115Supported in:21162117[Rules](/chronicle/docs/detection/default-rules)2118[Search](/chronicle/docs/investigation/udm-search)21192120```2121arrays.index_to_float(array, index)21222123```21242125#### Description21262127Returns the element at the given index of an array. The element at that index is returned as a float.21282129The 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.21322133#### Param data types21342135`ARRAY_STRINGS|ARRAY_INTS|ARRAY_FLOATS`, `INT`21362137#### Return type21382139`FLOAT`21402141#### Code samples21422143##### Example 121442145The following example fetches an element at index 1 from an array of floats.21462147```2148arrays.index_to_float([1.2, 2.1, 3.5, 4.6], 1) // 2.121492150```21512152##### Example 221532154The following example fetches an element at index -1 from an array of floats.21552156```2157arrays.index_to_float([1.2, 2.1, 3.5, 4.6], 0-1) // 4.621582159```21602161##### Example 321622163The following example fetches an element for an index greater than the size of the array.21642165```2166arrays.index_to_float([1.2, 2.1, 3.5, 4.6], 6) // 0.021672168```21692170##### Example 421712172The following example fetches an element from an empty array.21732174```2175arrays.index_to_float([], 0) // 0.021762177```21782179##### Example 521802181The following example fetches an element at index 1 from a string array.21822183```2184arrays.index_to_float(["1.2", "3.3", "2.4"], 1) // 3.321852186```21872188##### Example 621892190The following example fetches an element at index 2 from an array of integers.21912192```2193arrays.index_to_float([1, 3, 2], 2) // 2.021942195```2196219721982199### arrays.index\_to\_int22002201Supported in:22022203[Rules](/chronicle/docs/detection/default-rules)2204[Search](/chronicle/docs/investigation/udm-search)22052206```2207arrays.index_to_int(array_of_inputs, index)22082209```22102211#### Description22122213Returns the value at a given index in an array as an integer.22142215The 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.22182219#### Param data types22202221`ARRAY_STRINGS|ARRAY_INTS|ARRAY_FLOATS`, `INT`22222223#### Return type22242225`INT`22262227#### Code samples22282229##### Example 122302231This function call returns 0 when the value at the index is a non-numeric string.22322233```2234arrays.index_to_int(["str0", "str1", "str2"], 1) = 022352236```22372238##### Example 222392240This function returns the element at index -1.22412242```2243arrays.index_to_int(["44", "11", "22", "33"], 0-1) = 3322442245```22462247##### Example 322482249Returns 0 for the out-of-bounds element.22502251```2252arrays.index_to_int(["44", "11", "22", "33"], 5) = 022532254```22552256##### Example 422572258This function fetches the element from the float array at index 1.22592260```2261arrays.index_to_int([1.100000, 1.200000, 1.300000], 1) = 122622263```22642265##### Example 522662267This function fetches the element from the int array at index 0.22682269```2270arrays.index_to_int([1, 2, 3], 0) = 122712272```2273227422752276### arrays.index\_to\_str22772278Supported in:22792280[Rules](/chronicle/docs/detection/default-rules)2281[Search](/chronicle/docs/investigation/udm-search)22822283```2284arrays.index_to_str(array, index)22852286```22872288#### Description22892290Returns 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.22942295#### Param data types22962297`ARRAY_STRINGS|ARRAY_INTS|ARRAY_FLOATS`, `INT`22982299#### Return type23002301`STRING`23022303#### Code samples23042305##### Example 123062307The following example fetches an element at index 1 from an array of strings.23082309```2310arrays.index_to_str(["test1", "test2", "test3", "test4"], 1) // "test2"23112312```23132314##### Example 223152316The following example fetches an element at index -1 (last element of the array)2317from an array of strings.23182319```2320arrays.index_to_str(["test1", "test2", "test3", "test4"], 0-1) // "test4"23212322```23232324##### Example 323252326The following example fetches an element for an index greater than the size of the array, which returns an empty string.23272328```2329arrays.index_to_str(["test1", "test2", "test3", "test4"], 6) // ""23302331```23322333##### Example 423342335The following example fetches an element from an empty array.23362337```2338arrays.index_to_str([], 0) // ""23392340```23412342##### Example 523432344The following example fetches an element at index 0 from an array of floats. The output is returned as a string.23452346```2347arrays.index_to_str([1.200000, 3.300000, 2.400000], 0) // "1.2"23482349```23502351##### Example 623522353The following example fetches an element at index 2 from an array of integers. The output is in the form of a string.23542355```2356arrays.index_to_str([1, 3, 2], 2) // "2"23572358```2359236023612362### cast.as\_bool23632364Supported in:23652366[Rules](/chronicle/docs/detection/default-rules)2367[Search](/chronicle/docs/investigation/udm-search)23682369```2370cast.as_bool(string_or_int)23712372```23732374#### Description23752376Function converts an int or string value into a bool value. Function calls with2377values that cannot be casted will return FALSE. Returns TRUE only for integer 12378and case insensitive string 'true'.23792380#### Param data types23812382`INT|STRING`23832384#### Return type23852386`BOOL`23872388#### Code samples23892390##### Example 123912392This example shows how to cast a non-boolean string23932394```2395cast.as_bool("123") = false23962397```23982399##### Example 224002401Truthy integer (1)24022403```2404cast.as_bool(1) = true24052406```24072408##### Example 324092410Truthy string24112412```2413cast.as_bool("true") = true24142415```24162417##### Example 424182419Capital truthy string24202421```2422cast.as_bool("TRUE") = true24232424```24252426##### Example 524272428Negative integer24292430```2431cast.as_bool(0-1) = false24322433```24342435##### Example 624362437False integer (0)24382439```2440cast.as_bool(0) = false24412442```24432444##### Example 724452446empty string24472448```2449cast.as_bool("") = false24502451```2452245324542455### cast.as\_float24562457Supported in:24582459[Rules](/chronicle/docs/detection/default-rules)2460[Search](/chronicle/docs/investigation/udm-search)24612462```2463cast.as_float(string_to_cast)24642465```24662467#### Description24682469Converts a numeric string into a float. Any function calls with values that2470cannot be casted return 0. Floats maintain precision up to 7 decimal digits.24712472#### Param data types24732474`STRING`24752476#### Return type24772478`FLOAT`24792480#### Code samples24812482##### Example 124832484Casting a non-numeric string returns 0.24852486```2487cast.as_float("str") = 0.000000024882489```24902491##### Example 224922493Casting an empty string returns 0.24942495```2496cast.as_float("") = 0.000000024972498```24992500##### Example 325012502Casting a valid numeric string returns a float value.25032504```2505cast.as_float("1.012345678") = 1.012345625062507```2508250925102511### cast.as\_string25122513Supported in:25142515[Rules](/chronicle/docs/detection/default-rules)2516[Search](/chronicle/docs/investigation/udm-search)25172518```2519cast.as_string(int_or_bytes_or_bool, optional_default_string)25202521```25222523#### Description25242525The `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.25262527#### Param data types25282529`INT|BYTES|BOOL`, `STRING`25302531#### Return type25322533`STRING`25342535#### Code samples25362537##### Integer to String Conversion25382539The function converts the integer `123` to the string `"123"`.25402541```2542cast.as_string(123) = "123"25432544```25452546##### Float to String Conversion25472548The function converts the float `2.25` to the string `"2.25"`.25492550```2551cast.as_string(2.25) = "2.25"25522553```25542555##### Bytes to String Conversion25562557The function converts the raw binary `b'01` to the string `"\x01"`.25582559```2560cast.as_string(b'01, "") = "\x01"25612562```25632564##### Boolean to String Conversion25652566The function converts the boolean `true` to the string `"true"`.25672568```2569cast.as_string(true, "") = "true"25702571```25722573##### Failed Conversion (Defaults to the Optionally Provided String)25742575The function defaults to the string `"casting error"` when the value provided is invalid.25762577```2578cast.as_string(9223372036854775808, "casting error") = "casting error"25792580```2581258225832584### fingerprint25852586Supported in:25872588[Rules](/chronicle/docs/detection/default-rules)25892590```2591hash.fingerprint2011(byteOrString)25922593```25942595#### Description25962597This function calculates the `fingerprint2011` hash of an input byte sequence2598or string. This function returns an unsigned `INT` value in the range `[2, 0xFFFFFFFFFFFFFFFF]`.25992600**Note:** This function shouldn't be used as a cryptographic secure hash.26012602#### Param data types26032604`BTYE`, `STRING`26052606#### Return type26072608`INT`26092610#### Code sample26112612```2613id_fingerprint = hash.fingerprint2011("user123")26142615```2616261726182619### group26202621Supported in:26222623[Search](/chronicle/docs/investigation/udm-search)26242625```2626group(field1, field2, field3, ...)26272628```26292630#### Description26312632Group fields of a similar type into a placeholder variable.26332634In UDM search, [grouped2635fields](/chronicle/docs/investigation/udm-search#search_grouped_fields) are used to search across multiple fields of a similar type. The group2636function is similar to grouped fields except that it lets you select which fields you want2637grouped 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).26382639**Note:** For search, you can use grouped fields in the events section, but not in2640the match and outcome sections.26412642#### Code samples26432644**Example 1**26452646Group all the IP addresses together and provide a descending count of the most prevalent IP address in the time range scanned.26472648```2649$ip = group(principal.ip, about.ip, target.ip)2650$ip != ""2651match:2652 $ip2653outcome:2654 $count = count_distinct(metadata.id)2655order:2656 $count desc26572658```2659266026612662### hash.sha25626632664Supported in:26652666[Rules](/chronicle/docs/detection/default-rules)26672668```2669hash.sha256(string)26702671```26722673#### Description26742675Returns a SHA-256 hash of the input string.26762677#### Param data types26782679`STRING`26802681#### Return type26822683`STRING`26842685#### Code samples26862687##### Example 126882689This example shows the SHA-256 hash when the input is a valid string.26902691```2692hash.sha256("str") = "8c25cb3686462e9a86d2883c5688a22fe738b0bbc85f458d2d2b5f3f667c6d5a"26932694```26952696##### Example 226972698This example shows the SHA-256 hash when the input is an empty string.26992700```2701hash.sha256("") = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"27022703```2704270527062707### math.abs27082709Supported in:27102711[Rules](/chronicle/docs/detection/default-rules)2712[Search](/chronicle/docs/investigation/udm-search)27132714```2715math.abs(numericExpression)27162717```27182719#### Description27202721Returns the absolute value of an integer or float expression.27222723#### Param data types27242725`NUMBER`27262727#### Return type27282729`NUMBER`27302731#### Code samples27322733##### Example 127342735This example returns True if the event was more than 5 minutes from the time2736specified (in seconds from the Unix epoch), regardless of whether the event came2737before or after the time specified. A call to `math.abs` cannot depend on2738multiple variables or placeholders. For example, you cannot replace the2739hardcoded time value of 1643687343 in the following example with2740`$e2.metadata.event_timestamp.seconds`.27412742```2743300 < math.abs($e1.metadata.event_timestamp.seconds - 1643687343)27442745```2746274727482749### math.ceil27502751Supported in:27522753[Rules](/chronicle/docs/detection/default-rules)2754[Search](/chronicle/docs/investigation/udm-search)27552756```2757math.ceil(number)27582759```27602761#### Description27622763Returns 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.27642765#### Param data types27662767`FLOAT`27682769#### Return type27702771`INT`27722773#### Code samples27742775This section contains examples of using `math.ceil`.27762777##### Example 127782779This example returns the ceil of a whole number.27802781```2782math.ceil(2.000000) = 227832784```27852786##### Example 227872788This example returns the ceil of a negative number.27892790```2791math.ceil(0-1.200000) = -127922793```27942795##### Example 327962797This example returns 0 as the ceil of a number that is too big for a 64 bit integer.27982799```2800math.ceil(184467440737095516160.0) = 028012802```2803280428052806### math.floor28072808Supported in:28092810[Rules](/chronicle/docs/detection/default-rules)2811[Search](/chronicle/docs/investigation/udm-search)28122813```2814math.floor(float_val)28152816```28172818#### Description28192820Returns 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.28212822#### Param data types28232824`FLOAT`28252826#### Return type28272828`INT`28292830#### Code samples28312832##### Example 128332834This example shows a positive number case.28352836```2837math.floor(1.234568) = 128382839```28402841##### Example 228422843This example shows a negative number case.28442845```2846math.floor(0-1.234568) = -228472848```28492850##### Example 328512852This example shows a zero case.28532854```2855math.floor(0.000000) = 028562857```2858285928602861### math.geo\_distance28622863Supported in:28642865[Rules](/chronicle/docs/detection/default-rules)28662867```2868math.geo_distance(longitude1, latitude1, longitude2, latitude2))28692870```28712872#### Description28732874Returns the distance between two geographic locations (coordinates) in meters.2875Returns -1 if the coordinates are invalid.28762877#### Parameter data types28782879`FLOAT`, `FLOAT`, `FLOAT`, `FLOAT`28802881#### Return type28822883`FLOAT`28842885#### Code samples28862887##### Example 128882889The following example returns the distance when all parameters are valid2890coordinates:28912892```2893math.geo_distance(-122.020287, 37.407574, -122.021810, 37.407574) = 134.56431828942895```28962897##### Example 228982899The following example returns the distance when one of the parameters is a2900truncated coordinate:29012902```2903math.geo_distance(-122.000000, 37.407574, -122.021810, 37.407574) = 1926.42190529042905```29062907##### Example 329082909The following example returns `-1` when one of the parameters is an invalid2910coordinate:29112912```2913math.geo_distance(0-122.897680, 37.407574, 0-122.021810, 97.407574) = -1.00000029142915```29162917##### Example 429182919The following example returns `0` when coordinates are the same:29202921```2922math.geo_distance(-122.897680, 37.407574, -122.897680, 37.407574) = 0.00000029232924```2925292629272928### math.is\_increasing29292930Supported in:29312932[Rules](/chronicle/docs/detection/default-rules)2933[Search](/chronicle/docs/investigation/udm-search)29342935```2936math.is_increasing(num1, num2, num3)29372938```29392940#### Description29412942Takes a list of numeric values (integers or doubles) and returns `True` if2943the values are in ascending order, and `False` otherwise.29442945#### Param data types29462947`INT|FLOAT`, `INT|FLOAT`, `INT|FLOAT`29482949#### Return type29502951`BOOL`29522953#### Code samples29542955##### Example 129562957This example includes timestamp-like values in seconds.29582959```2960math.is_increasing(1716769112, 1716769113, 1716769114) = true29612962```29632964##### Example 229652966This example includes one negative double, one zero INT64, and one positive INT64 values.29672968```2969math.is_increasing(-1.200000, 0, 3) = true29702971```29722973##### Example 329742975This example includes one negative double, one zero INT64, and one negative INT64 values.29762977```2978math.is_increasing(0-1.200000, 0, 0-3) = false29792980```29812982##### Example 429832984This example includes two negative doubles and one zero INT64 value.29852986```2987math.is_increasing(0-1.200000, 0-1.50000, 0) = false29882989```29902991##### Example 529922993This example includes one negative double and two values that are the same.29942995```2996math.is_increasing(0-1.200000, 0, 0) = false29972998```2999300030013002### math.log30033004Supported in:30053006[Rules](/chronicle/docs/detection/default-rules)3007[Search](/chronicle/docs/investigation/udm-search)30083009```3010math.log(numericExpression)30113012```30133014#### Description30153016Returns the natural log value of an integer or float expression.30173018#### Param data types30193020`NUMBER`30213022#### Return type30233024`NUMBER`30253026#### Code samples30273028##### Example 130293030```3031math.log($e1.network.sent_bytes) > 2030323033```3034303530363037### math.pow30383039Supported in:30403041[Rules](/chronicle/docs/detection/default-rules)3042[Search](/chronicle/docs/investigation/udm-search)30433044```3045math.pow(base, exponent)30463047```30483049#### Description30503051Returns the value of the first arg raised to the power of the second arg. Returns 0 in case of overflow.30523053#### Param data types30543055base: `INT|FLOAT`3056exponent: `INT|FLOAT`30573058#### Return type30593060`FLOAT`30613062#### Code samples30633064##### Example 130653066This example shows an integer case.30673068```3069math.pow(2, 2) // 4.0030703071```30723073##### Example 230743075This example shows a fraction base case.30763077```3078math.pow(2.200000, 3) // 10.64830793080```30813082##### Example 330833084This example shows a fraction base and power case.30853086```3087math.pow(2.200000, 1.200000) // 2.57577130883089```30903091##### Example 430923093This example shows a negative power case.30943095```3096math.pow(3, 0-3) // 0.03703730973098```30993100##### Example 531013102This example shows a fraction power case.31033104```3105math.pow(3, 0-1.200000) // 0.26758131063107```31083109##### Example 631103111This example shows a negative base case.31123113```3114math.pow(0-3, 0-3) // -0.03703731153116```31173118##### Example 731193120This example shows a zero base case.31213122```3123math.pow(0, 3) // 031243125```31263127##### Example 831283129This example shows a zero power case.31303131```3132math.pow(9223372036854775807, 0) // 131333134```31353136##### Example 931373138This example shows a large base case.31393140```3141math.pow(9223372036854775807, 1.200000) // 5726215288975159354982431423143```3144314531463147### math.random31483149Supported in:31503151[Rules](/chronicle/docs/detection/default-rules)3152[Search](/chronicle/docs/investigation/udm-search)31533154```3155math.random()31563157```31583159#### Description31603161Generates a pseudo-random value of type DOUBLE in the range of `[0, 1)`, inclusive of 0 and exclusive of 1.31623163#### Return type31643165`FLOAT`31663167#### Code samples31683169The following example checks whether the random value is in the range `[0, 1)`.3170`none3171if(math.random() >= 0 and math.random() < 1) = true`31723173### math.round31743175Supported in:31763177[Search](/chronicle/docs/investigation/udm-search)31783179```3180math.round(numericExpression, decimalPlaces)31813182```31833184#### Description31853186Returns a value rounded to the nearest integer or to the specified number of decimal places.31873188#### Param data types31893190`NUMBER`31913192#### Return type31933194`NUMBER`31953196#### Code samples31973198```3199math.round(10.7) // returns 113200math.round(1.2567, 2) // returns 1.253201math.round(0-10.7) // returns -113202math.round(0-1.2) // returns -13203math.round(4) // returns 4, math.round(integer) returns the integer32043205```3206320732083209### math.sqrt32103211Supported in:32123213[Rules](/chronicle/docs/detection/default-rules)3214[Search](/chronicle/docs/investigation/udm-search)32153216```3217math.sqrt(number)32183219```32203221#### Description32223223Returns the square root of the given number. Returns 0 in case of negative numbers.32243225#### Param data types32263227`INT|FLOAT`32283229#### Return type32303231`FLOAT`32323233#### Code samples32343235##### Example 132363237This example returns the square root of an int argument.32383239```3240math.sqrt(3) = 1.73205132413242```32433244##### Example 232453246This example returns the square root of a negative int argument.32473248```3249math.sqrt(-3) = 0.00000032503251```32523253##### Example 332543255This example returns the square root of zero argument.32563257```3258math.sqrt(0) = 0.00000032593260```32613262##### Example 432633264This example returns the square root of a float argument.32653266```3267math.sqrt(9.223372) = 3.03700032683269```32703271##### Example 532723273This example returns the square root of a negative float argument.32743275```3276math.sqrt(0-1.200000) = 0.00000032773278```3279328032813282### metrics32833284Supported in:32853286[Rules](/chronicle/docs/detection/default-rules)32873288Metrics functions can aggregate large amounts of historical data. You can use3289this in your rule using `metrics.functionName()` in the outcome3290section.32913292For more information, see [YARA-L Metrics](/chronicle/docs/detection/metrics-functions).32933294### net.ip\_in\_range\_cidr32953296Supported in:32973298[Rules](/chronicle/docs/detection/default-rules)3299[Search](/chronicle/docs/investigation/udm-search)33003301```3302net.ip_in_range_cidr(ipAddress, subnetworkRange)33033304```33053306#### Description33073308Returns `true` when the given IP address is within the specified subnetwork.33093310You can use YARA-L to search for UDM events across all of the IP addresses3311within a subnetwork using the `net.ip_in_range_cidr()` statement.3312Both IPv4 and IPv6 are supported.33133314To search across a range of IP addresses, specify an IP UDM field and a CIDR3315range. YARA-L can handle both singular and repeating IP address fields.33163317To 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.33183319#### Param data types33203321`STRING`, `STRING`33223323#### Return type33243325`BOOL`33263327#### Code samples33283329##### Example 133303331IPv4 example:33323333```3334net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/24")33353336```33373338##### Example 233393340IPv6 example:33413342```3343net.ip_in_range_cidr($e.network.dhcp.yiaddr, "2001:db8::/32")33443345```33463347For 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).)33483349### re.regex33503351Supported in:33523353[Rules](/chronicle/docs/detection/default-rules)3354[Search](/chronicle/docs/investigation/udm-search)33553356You can define regular expression matching in YARA-L 2.0 using either of the following syntax:33573358* Using YARA-L syntax — Related to events.3359 The following is a generic representation of this syntax:33603361```3362 $e.field = /regex/33633364```3365* Using YARA-L syntax — As a function taking in the following parameters:33663367 + Field the regular expression is applied to.3368 + Regular expression specified as a string.33693370 The following is a generic representation of this syntax:33713372```3373 re.regex($e.field, `regex`)33743375```33763377#### Description33783379This 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.33803381##### Notes33823383* 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 match3386 `"fullest"`, `"lawfull"`, and `"joyfully"`.3387* If the UDM field includes newline characters, the `regexp` only matches the3388 first line of the UDM field. To enforce full UDM field matching, add a `(?s)` to3389 the regular expression. For example, replace `/.*allUDM.*/` with3390 `/(?s).*allUDM.*/`.3391* You can use the `nocase` modifier after strings to indicate that the search3392 should ignore capitalization.33933394#### Param data types33953396`STRING`, `STRING`33973398#### Param expression types33993400`ANY`, `ANY`34013402#### Return type34033404`BOOL`34053406#### Code samples34073408##### Example 134093410```3411// Equivalent to $e.principal.hostname = /google/3412re.regex($e.principal.hostname, "google")34133414```3415341634173418### re.capture34193420Supported in:34213422[Rules](/chronicle/docs/detection/default-rules)3423[Search](/chronicle/docs/investigation/udm-search)34243425```3426re.capture(stringText, regex)34273428```34293430#### Description34313432Captures (extracts) data from a string using the regular expression pattern3433provided in the argument.34343435This function takes two arguments:34363437* `stringText`: the original string to search.3438* `regex`: the regular expression indicating the pattern to search for.34393440The regular expression can contain 0 or 1 capture groups in parentheses. If the3441regular expression contains 0 capture groups, the function returns the first3442entire matching substring. If the regular expression contains 1 capture group,3443it returns the first matching substring for the capture group. Defining two or3444more capture groups returns a compiler error.34453446#### Param data types34473448`STRING`, `STRING`34493450#### Return type34513452`STRING`34533454#### Code samples34553456##### Example 134573458In this example, if `$e.principal.hostname` contains "aaa1bbaa2" the following would be true, because the function3459returns the first instance. This example has no capture groups.34603461```3462"aaa1" = re.capture($e.principal.hostname, "a+[1-9]")34633464```34653466##### Example 234673468This example captures everything after the @ symbol in an email. If the3469`$e.network.email.from` field is `test@google.com`, the example returns3470`google.com`. The following example contains one capture group.34713472```3473"google.com" = re.capture($e.network.email.from , "@(.*)")34743475```34763477##### Example 334783479If the regular expression does not match any substring in the text, the3480function returns an empty string. You can omit events where no match occurs3481by excluding the empty string, which is especially important when you are3482using `re.capture()` with an inequality:34833484```3485// Exclude the empty string to omit events where no match occurs.3486"" != re.capture($e.network.email.from , "@(.*)")34873488// Exclude a specific string with an inequality.3489"google.com" != re.capture($e.network.email.from , "@(.*)")34903491```3492349334943495### re.replace34963497Supported in:34983499[Rules](/chronicle/docs/detection/default-rules)3500[Search](/chronicle/docs/investigation/udm-search)35013502```3503re.replace(stringText, replaceRegex, replacementText)35043505```35063507#### Description35083509Performs a regular expression replacement.35103511This function takes three arguments:35123513* `stringText`: the original string.3514* `replaceRegex`: the regular expression indicating the pattern to search for.3515* `replacementText`: The text to insert into each match.35163517Returns a new string derived from the original `stringText`, where all3518substrings that match the pattern in `replaceRegex` are replaced with the value in3519`replacementText`. You can use backslash-escaped digits (`\1` to `\9`) within3520`replacementText` to insert text matching the corresponding parenthesized group3521in the `replaceRegex` pattern. Use `\0` to refer to the entire matching text.35223523The function replaces non-overlapping matches and will prioritize replacing the3524first occurrence found. For example, `re.replace("banana", "ana", "111")`3525returns the string "b111na".35263527#### Param data types35283529`STRING`, `STRING`, `STRING`35303531#### Return type35323533`STRING`35343535#### Code samples35363537##### Example 135383539This example captures everything after the `@` symbol in an email, replaces `com`3540with `org`, and then returns the result. Notice the use of nested functions.35413542```3543"email@google.org" = re.replace($e.network.email.from, "com", "org")35443545```35463547##### Example 235483549This example uses backslash-escaped digits in the `replacementText` argument to3550reference matches to the `replaceRegex` pattern.35513552```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 )35583559```35603561##### Example 335623563Note the following cases when dealing with empty strings and `re.replace()`:35643565Using empty string as `replaceRegex`:35663567```3568// In the function call below, if $e.principal.hostname contains "name",3569// the result is: 1n1a1m1e1, because an empty string is found next to3570// every character in `stringText`.3571re.replace($e.principal.hostname, "", "1")35723573```35743575To replace an empty string, you can use `"^$"` as `replaceRegex`:35763577```3578// In the function call below, if $e.principal.hostname contains the empty3579// string, "", the result is: "none".3580re.replace($e.principal.hostname, "^$", "none")35813582```3583358435853586### sample\_rate35873588Supported in:35893590[Rules](/chronicle/docs/detection/default-rules)35913592```3593optimization.sample_rate(byteOrString, rateNumerator, rateDenominator)35943595```35963597#### Description35983599This function determines whether to include an event based on a deterministic3600sampling strategy. This function returns:36013602* `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.36053606This function is useful for optimization scenarios where you want to process3607only a subset of events. Equivalent to:36083609```3610hash.fingerprint2011(byteOrString) % rateDenominator < rateNumerator36113612```36133614#### Param data types36153616* byteOrString: Expression that evaluates to either a `BYTE` or `STRING`.3617* rateNumerator: 'INT'3618* rateDenominator: 'INT'36193620#### Return type36213622`BOOL`36233624#### Code sample36253626```3627events:3628 $e.metadata.event_type = "NETWORK_CONNECTION"3629 $asset_id = $e.principal.asset.asset_id3630 optimization.sample_rate($e.metadata.id, 1, 5) // Only 1 out of every 5 events36313632 match:3633 $asset_id over 1h36343635 outcome:3636 $event_count = count_distinct($e.metadata.id)3637 // estimate the usage by multiplying by the inverse of the sample rate3638 $usage_past_hour = sum(5.0 * $e.network.sent_bytes)36393640 condition:3641 // Requiring a certain number of events after sampling avoids bias (e.g. a3642 // device with just 1 connection will still show up 20% of the time and3643 // if we multiply that traffic by 5, we'll get an incorrect estimate)3644 $e and ($usage_past_hour > 1000000000) and $event_count >= 10036453646```3647364836493650### strings.base64\_decode36513652Supported in:36533654[Rules](/chronicle/docs/detection/default-rules)3655[Search](/chronicle/docs/investigation/udm-search)36563657```3658strings.base64_decode(encodedString)36593660```36613662#### Description36633664Returns a string containing the base64 decoded version of the encoded string.36653666This function takes one base64 encoded string as an argument. If `encodedString`3667is not a valid base64 encoded string, the function returns `encodedString` unchanged.36683669#### Param data types36703671`STRING`36723673#### Return type36743675`STRING`36763677#### Code samples36783679##### Example 136803681```3682"test" = strings.base64_decode($e.principal.domain.name)36833684```3685368636873688### strings.coalesce36893690Supported in:36913692[Rules](/chronicle/docs/detection/default-rules)3693[Search](/chronicle/docs/investigation/udm-search)36943695```3696strings.coalesce(a, b, c, ...)36973698```36993700#### Description37013702This 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.37033704The 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.37053706#### Param data types37073708`STRING`37093710#### Return type37113712`STRING`37133714#### Code samples37153716##### Example 137173718The following example includes string variables as arguments. The condition3719evaluates to true when (1) `$e.network.email.from` is `suspicious@gmail.com` or3720(2) `$e.network.email.from` is empty and `$e.network.email.to` is3721`suspicious@gmail.com`.37223723```3724"suspicious@gmail.com" = strings.coalesce($e.network.email.from, $e.network.email.to)37253726```37273728##### Example 237293730The following example calls the `coalesce` function with more than two3731arguments. This condition compares the first non-null IP address from event `$e`3732against values in the reference list `ip_watchlist`. The order that the3733arguments are coalesced in this call is the same as the order they are3734enumerated in the rule condition:373537361. `$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.37413742```3743strings.coalesce($e.principal.ip, $e.src.ip, $e.target.ip, "No IP") in %ip_watchlist37443745```37463747##### Example 337483749The following example attempts to coalesce `principal.hostname` from event3750`$e1` and event `$e2`. It will return a compiler error because the arguments are3751different event variables.37523753```3754// returns a compiler error3755"test" = strings.coalesce($e1.principal.hostname, $e2.principal.hostname)37563757```3758375937603761### strings.concat37623763Supported in:37643765[Rules](/chronicle/docs/detection/default-rules)3766[Search](/chronicle/docs/investigation/udm-search)37673768```3769strings.concat(a, b, c, ...)37703771```37723773#### Description37743775Returns the concatenation of an unlimited number of items, each of which can be3776a string, integer, or float.37773778If any arguments are event fields, the attributes must be from the same event.37793780#### Param data types37813782`STRING`, `FLOAT`, `INT`37833784#### Return type37853786`STRING`37873788#### Code samples37893790##### Example 137913792The following example includes a string variable and integer variable as3793arguments. Both `principal.hostname` and `principal.port` are from the same3794event, `$e`, and are concatenated to return a string.37953796```3797"google:80" = strings.concat($e.principal.hostname, ":", $e.principal.port)37983799```38003801##### Example 238023803The following example includes a string variable and string literal as arguments.38043805```3806"google-test" = strings.concat($e.principal.hostname, "-test") // Matches the event when $e.principal.hostname = "google"38073808```38093810##### Example 338113812The following example includes a string variable and float literal as arguments.3813When represented as strings, floats that are whole numbers are formatted without3814the decimal point (for example, 1.0 is represented as "1"). Additionally,3815floats that exceed sixteen decimal digits are truncated to the sixteenth decimal3816place.38173818```3819"google2.5" = strings.concat($e.principal.hostname, 2.5)38203821```38223823##### Example 438243825The following example includes a string variable, string literal,3826integer variable, and float literal as arguments. All variables are from the3827same event, `$e`, and are concatenated with the literals to return a string.38283829```3830"google-test802.5" = strings.concat($e.principal.hostname, "-test", $e.principal.port, 2.5)38313832```38333834##### Example 538353836The following example attempts to concatenate principal.port from event `$e1`,3837with `principal.hostname` from event `$e2`. It will return a compiler error3838because the arguments are different event variables.38393840```3841// Will not compile3842"test" = strings.concat($e1.principal.port, $e2.principal.hostname)38433844```3845384638473848### strings.contains38493850Supported in:38513852[Rules](/chronicle/docs/detection/default-rules)3853[Search](/chronicle/docs/investigation/udm-search)38543855```3856strings.contains( str, substr )38573858```38593860#### Description38613862Returns true if a given string contains the specified substring. Otherwise it returns false.38633864#### Param data types38653866`STRING`, `STRING`38673868#### Return type38693870`BOOL`38713872#### Code samples38733874##### Example 138753876This example returns true because the string has a substring "is".38773878```3879strings.contains("thisisastring", "is") = true38803881```38823883##### Example 238843885This example returns false because the string does not have substring "that".38863887```3888strings.contains("thisisastring", "that") = false38893890```3891389238933894### strings.count\_substrings38953896Supported in:38973898[Rules](/chronicle/docs/detection/default-rules)3899[Search](/chronicle/docs/investigation/udm-search)39003901```3902strings.count_substrings(string_to_search_in, substring_to_count)39033904```39053906#### Description39073908When given a string and a substring, returns an int64 of the count of non-overlapping occurrences of the substring within the string.39093910#### Param data types39113912`STRING`, `STRING`39133914#### Return type39153916`INT`39173918#### Code samples39193920This section contains examples that calculate the number of times a substring appears in a given string.39213922##### Example 139233924This example uses a non-null string and a non-null single substring character.39253926```3927strings.count_substrings("this`string`has`four`backticks", "`") = 439283929```39303931##### Example 239323933This example uses a non-null string and a non-null substring greater than one character.39343935```3936strings.count_substrings("str", "str") = 139373938```39393940##### Example 339413942This example uses a non-null string and an empty substring.39433944```3945strings.count_substrings("str", "") = 039463947```39483949##### Example 439503951This example uses an empty string and a non-null substring greater than one character.39523953```3954strings.count_substrings("", "str") = 039553956```39573958##### Example 539593960This example uses an empty string and an empty substring.39613962```3963strings.count_substrings("", "") = 039643965```39663967##### Example 639683969This example uses a non-null string and a non-null substring that is greater than one character and greater than one occurrence.39703971```3972strings.count_substrings("fooABAbarABAbazABA", "AB") = 339733974```39753976##### Example 739773978This 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 occurrences39793980```3981strings.count_substrings("ABABABA", "ABA") = 239823983```3984398539863987### strings.extract\_domain39883989Supported in:39903991[Rules](/chronicle/docs/detection/default-rules)3992[Search](/chronicle/docs/investigation/udm-search)39933994```3995strings.extract_domain(url_string)39963997```39983999#### Description40004001Extracts the domain from a string.40024003**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.40044005#### Param data types40064007`STRING`40084009#### Return type40104011`STRING`40124013#### Code samples40144015##### Example 140164017This example shows an empty string40184019```4020strings.extract_domain("") = ""40214022```40234024##### Example 240254026random string, not a URL40274028```4029strings.extract_domain("1234") = ""40304031```40324033##### Example 340344035multiple backslaches40364037```4038strings.extract_domain("\\\\") = ""40394040```40414042##### Example 440434044non-alphabet characters handled gracefully40454046```4047strings.extract_domain("http://例子.卷筒纸.中国") = "卷筒纸.中国"40484049```40504051##### Example 540524053handling URIs40544055```4056strings.extract_domain("mailto:?to=&subject=&body=") = ""40574058```40594060##### Example 640614062multiple characters before actual URL40634064```4065strings.extract_domain(" \t !$5*^)&dahgsdfs;http://www.google.com") = "google.com"40664067```40684069##### Example 740704071special characters in URI `#`40724073```4074strings.extract_domain("test#@google.com") = ""40754076```40774078##### Example 840794080special characters in URL `#`40814082```4083strings.extract_domain("https://test#@google.com") = ""40844085```40864087##### Example 940884089positive test case40904091```4092strings.extract_domain("https://google.co.in") = "google.co.in"40934094```4095409640974098### strings.extract\_hostname40994100Supported in:41014102[Rules](/chronicle/docs/detection/default-rules)4103[Search](/chronicle/docs/investigation/udm-search)41044105```4106strings.extract_hostname(string)41074108```41094110#### Description41114112Extracts the hostname from a string. This function is case sensitive.41134114#### Param data types41154116`STRING`41174118#### Return type41194120`STRING`41214122#### Code samples41234124##### Example 141254126This example returns an empty string.41274128```4129strings.extract_hostname("") = ""41304131```41324133##### Example 241344135random string, not a URL41364137```4138strings.extract_hostname("1234") = "1234"41394140```41414142##### Example 341434144multiple backslashes41454146```4147strings.extract_hostname("\\\\") = ""41484149```41504151##### Example 441524153non-English characters handled gracefully41544155```4156strings.extract_hostname("http://例子.卷筒纸.中国") = "例子.卷筒纸.中国"41574158```41594160##### Example 541614162handling URIs41634164```4165strings.extract_hostname("mailto:?to=&subject=&body=") = "mailto"41664167```41684169##### Example 641704171multiple characters before actual URL41724173```4174strings.extract_hostname(" \t !$5*^)&dahgsdfs;http://www.google.com") = "www.google.com"41754176```41774178##### Example 741794180special characters in URI `#`41814182```4183strings.extract_hostname("test#@google.com") = "test"41844185```41864187##### Example 841884189special characters in URL `#`41904191```4192strings.extract_hostname("https://test#@google.com") = "test"41934194```4195419641974198### strings.from\_base6441994200Supported in:42014202[Rules](/chronicle/docs/detection/default-rules)4203[Search](/chronicle/docs/investigation/udm-search)42044205```4206strings.from_base64(base64_encoded_string)42074208```42094210#### Description42114212Function 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.42134214#### Param data types42154216`STRING`42174218#### Return type42194220`BYTES`42214222#### Code samples42234224##### Base64 Encoded String to Bytes Conversion42254226The function converts a base64 encoded string to its raw binary bytes representation.42274228```4229strings.from_base64("AAAAAG+OxVhtAm+d2sVuny/hW4oAAAAAAQAAAM0AAAA=") = b'000000006f8ec5586d026f9ddac56e9f2fe15b8a0000000001000000cd00000042304231```42324233##### Failed Conversion (Defaults to Empty Bytes)42344235The function defaults to empty bytes if the provided value in invalid.42364237```4238strings.from_base64("invalid-value") = b'42394240```4241424242434244### strings.from\_hex42454246Supported in:42474248[Rules](/chronicle/docs/detection/default-rules)4249[Search](/chronicle/docs/investigation/udm-search)42504251```4252strings.from_hex(hex_string)42534254```42554256#### Description42574258Returns the bytes associated with the given hex string.42594260#### Param data types42614262`STRING`42634264#### Return type42654266`BYTES`42674268#### Code samples42694270Get bytes associated with a given hex string.42714272##### Example 142734274This example shows non-hex character conversions.42754276```4277strings.from_hex("str") // returns empty bytes42784279```42804281##### Example 242824283This example shows input with empty string.42844285```4286strings.from_hex("") // returns empty bytes42874288```42894290##### Example 342914292This example shows hex string conversion.42934294```4295strings.from_hex("1234") // returns 1234 bytes42964297```42984299##### Example 443004301This example shows non-ASCII characters conversion.43024303```4304strings.from_hex("筒纸.中国") // returns empty bytes43054306```4307430843094310### strings.length43114312Supported in:43134314[Rules](/chronicle/docs/detection/default-rules)4315[Search](/chronicle/docs/investigation/udm-search)43164317```4318strings.length(string_value)43194320```43214322#### Description43234324Returns the number of characters in the input string.43254326#### Param data types43274328`STRING`43294330#### Return type43314332`INT`43334334#### Code samples43354336##### Example 143374338The following is an example with a string test.43394340```4341strings.length("str") = 343424343```43444345##### Example 243464347The following is an example with an empty string as input.43484349```4350strings.length("") = 043514352```43534354##### Example 343554356The following is an example with a special char string.43574358```4359strings.length("!@#$%^&*()-_") = 1243604361```43624363##### Example 443644365The following is an example with a string with spaces.43664367```4368strings.length("This is a test string") = 2143694370```4371437243734374### strings.ltrim43754376Supported in:43774378[Rules](/chronicle/docs/detection/default-rules)4379[Search](/chronicle/docs/investigation/udm-search)43804381```4382strings.ltrim(string_to_trim, cutset)43834384```43854386#### Description43874388Trims leading white spaces from a given string. This function removes leading characters present in that cutset.43894390#### Param data types43914392`STRING`, `STRING`43934394#### Return type43954396`STRING`43974398#### Code samples43994400The following are example use cases.44014402##### Example 144034404This example uses the same first and second argument.44054406```4407strings.ltrim("str", "str") = ""44084409```44104411##### Example 244124413This example uses an empty string as the second argument.44144415```4416strings.ltrim("str", "") = "str"44174418```44194420##### Example 344214422This example uses an empty string as the first argument, and a string as the second argument.44234424```4425strings.ltrim("", "str") = ""44264427```44284429##### Example 444304431This example uses strings that contain white spaces, and a string as the second argument.44324433```4434strings.ltrim("a aastraa aa ", " a") = "straa aa "44354436```4437443844394440### strings.reverse44414442Supported in:44434444[Rules](/chronicle/docs/detection/default-rules)4445[Search](/chronicle/docs/investigation/udm-search)44464447```4448strings.reverse(STRING)44494450```44514452#### Description44534454Returns a string that is the reverse of the input string.44554456#### Param data types44574458`STRING`44594460#### Return type44614462`STRING`44634464#### Code samples44654466##### Example 144674468The following example passes a short string.44694470```4471strings.reverse("str") = "rts" // The function returns 'rts'.44724473```44744475##### Example 244764477The following example passes an empty string.44784479```4480strings.reverse("") = ""44814482```44834484##### Example 344854486The following example passes a palindrome.44874488```4489strings.reverse("tacocat") = "tacocat"44904491```4492449344944495### strings.rtrim44964497Supported in:44984499[Rules](/chronicle/docs/detection/default-rules)4500[Search](/chronicle/docs/investigation/udm-search)45014502```4503strings.rtrim(string_to_trim, cutset)45044505```45064507#### Description45084509Trims trailing white spaces from a given string. Removes trailing characters that are present in that cutset.45104511#### Param data types45124513`STRING`, `STRING`45144515#### Return type45164517`STRING`45184519#### Code samples45204521The following are example use cases.45224523##### Example 145244525The following example passes the same string as the first and second argument.45264527```4528strings.rtrim("str", "str") = ""45294530```45314532##### Example 245334534The following example passes an empty string as the second argument.45354536```4537strings.rtrim("str", "") = "str"45384539```45404541##### Example 345424543The following example passes an empty string as the first argument and a non-empty string as the second argument.45444545```4546strings.rtrim("", "str") = ""45474548```45494550##### Example 445514552The following example passes a string containing white spaces as the first argument and a non-empty string as the second argument.45534554```4555strings.rtrim("a aastraa aa ", " a") = "a aasstr"45564557```4558455945604561### strings.to\_lower45624563Supported in:45644565[Rules](/chronicle/docs/detection/default-rules)4566[Search](/chronicle/docs/investigation/udm-search)45674568```4569strings.to_lower(stringText)45704571```45724573#### Description45744575This function takes an input string and returns a string after changing all4576characters to lowercase45774578#### Param data types45794580`STRING`45814582#### Return type45834584`STRING`45854586#### Code samples45874588##### Example 145894590The following example returns `true`.45914592```4593"test@google.com" = strings.to_lower($e.network.email.to)45944595```4596459745984599### strings.to\_upper46004601Supported in:46024603[Rules](/chronicle/docs/detection/default-rules)4604[Search](/chronicle/docs/investigation/udm-search)46054606```4607strings.to_upper(string_val)46084609```46104611#### Description46124613Returns the original string with all alphabetic characters in uppercase.46144615#### Param data types46164617`STRING`46184619#### Return type46204621`STRING`46224623#### Code samples46244625##### Example 146264627The following example returns the supplied argument in uppercase.46284629```4630strings.to_upper("example") = "EXAMPLE"46314632```4633463446354636### strings.trim46374638Supported in:46394640[Rules](/chronicle/docs/detection/default-rules)4641[Search](/chronicle/docs/investigation/udm-search)46424643```4644strings.trim(string_to_trim, cutset)46454646```46474648#### Description46494650Trims leading and trailing white spaces from a given string. Also, remove unwanted characters (specified by the cutset argument) from the input string.46514652#### Param data types46534654`STRING`, `STRING`46554656#### Return type46574658`STRING`46594660#### Code samples46614662The following are example use cases.46634664##### Example 146654666In the following example, the same string is passed as the input string and the cutset, which results in an empty string.46674668```4669strings.trim("str", "str") // ""46704671```46724673##### Example 246744675In 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.46764677```4678strings.trim("str", "") = "str"46794680```46814682##### Example 346834684In the following example, the function yields an empty string because the input string is already empty and there are no characters to remove.46854686```4687strings.trim("", "str") = ""46884689```46904691##### Example 446924693In the following example, the function yields str because the trim function removes the following:46944695* trailing whitespace in "a aastraa aa "4696* the characters specified in the cutset (space, a)46974698```4699strings.trim("a aastraa aa ", " a") = "str"47004701```4702470347044705### strings.url\_decode47064707Supported in:47084709[Rules](/chronicle/docs/detection/default-rules)4710[Search](/chronicle/docs/investigation/udm-search)47114712```4713strings.url_decode(url_string)47144715```47164717#### Description47184719Given a URL string, decode the escape characters and handle UTF-8 characters that have been encoded. Returns empty string if decoding fails.47204721#### Param data types47224723`STRING`47244725#### Return type47264727`STRING`47284729#### Code samples47304731##### Example 147324733This example shows a positive test case.47344735```4736strings.url_decode("three%20nine%20four") = "three nine four"47374738```47394740##### Example 247414742This example shows an empty string case.47434744```4745strings.url_decode("") // ""47464747```47484749##### Example 347504751This example shows non-alphabet characters handling.47524753```4754strings.url_decode("%E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B") // "上海+中國"47554756```47574758##### Example 447594760This example shows a sample URL decoding.47614762```4763strings.url_decode("http://www.google.com%3Fparam1%3D%22+1+%3E+2+%22%26param2%3D2%3B") // 'http://www.google.com?param1="+1+>+2+"¶m2=2;'47644765```4766476747684769### timestamp.as\_unix\_seconds47704771Supported in:47724773[Rules](/chronicle/docs/detection/default-rules)4774[Search](/chronicle/docs/investigation/udm-search)47754776```4777timestamp.as_unix_seconds(timestamp [, time_zone])47784779```47804781#### Description47824783This function returns an integer representing the number of seconds past a Unix epoch for the given timestamp string.47844785* `timestamp` is a string representing a valid epoch timestamp. The format needs4786 to be `%F %T`.4787* `time_zone` is optional and is a string representing a time zone. If4788 omitted, the default is `GMT`. You can specify time zones using string4789 literals. The options are as follows:4790 + The TZ database name, for example `America/Los_Angeles`. For more information, see the4791 [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".47944795Here are examples of valid `time_zone` specifiers, which you can pass as the second argument to time extraction functions:47964797```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"48034804```48054806#### Param data types48074808`STRING`, `STRING`48094810#### Return type48114812`INT`48134814#### Code samples48154816##### Example 148174818Valid epoch timestamp48194820```4821timestamp.as_unix_seconds("2024-02-22 10:43:00") = 170859858048224823```48244825##### Example 248264827Valid epoch timestamp with the America/New\_York time zone48284829```4830timestamp.as_unix_seconds("2024-02-22 10:43:00", "America/New_York") = 170861658048314832```4833483448354836### timestamp.current\_seconds48374838Supported in:48394840[Rules](/chronicle/docs/detection/default-rules)4841[Search](/chronicle/docs/investigation/udm-search)48424843```4844timestamp.current_seconds()48454846```48474848#### Description48494850Returns an integer representing the current time in Unix seconds. This is4851approximately equal to the detection timestamp and is based on when the rule is4852run. This function is a synonym of the function `timestamp.now()`.48534854#### Param data types48554856`NONE`48574858#### Return type48594860`INT`48614862#### Code samples48634864##### Example 148654866The following example returns `true` if the certificate has been expired for more4867than 24 hours. It calculates the time difference by subtracting the current Unix4868seconds, and then comparing using a greater than operator.48694870```487186400 < timestamp.current_seconds() - $e.network.tls.certificate.not_after48724873```4874487548764877### timestamp.get\_date48784879Supported in:48804881[Rules](/chronicle/docs/detection/default-rules)4882[Search](/chronicle/docs/investigation/udm-search)48834884```4885timestamp.get_date(unix_seconds [, time_zone])48864887```48884889#### Description48904891This function returns a string in the format `YYYY-MM-DD`, representing the day a timestamp is in.48924893* `unix_seconds` is an integer representing the number of seconds past Unix4894 epoch, such as `$e.metadata.event_timestamp.seconds`, or a placeholder4895 containing that value.4896* `time_zone` is optional and is a string representing a time\_zone. If4897 omitted, the default is "GMT". You can specify time zones using string4898 literals. The options are:4899 + The TZ database name, for example "America/Los\_Angeles". For more4900 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".49034904Here are examples of valid time\_zone specifiers, which you can pass as the second argument to time extraction functions:49054906```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"49124913```49144915#### Param data types49164917`INT`, `STRING`49184919#### Return type49204921`STRING`49224923#### Code samples49244925##### Example 149264927In this example, the `time_zone` argument is omitted, so it defaults to "GMT".49284929```4930$ts = $e.metadata.collected_timestamp.seconds49314932timestamp.get_date($ts) = "2024-02-19"49334934```49354936##### Example 249374938This example uses a string literal to define the `time_zone`.49394940```4941$ts = $e.metadata.collected_timestamp.seconds49424943timestamp.get_date($ts, "America/Los_Angeles") = "2024-02-20"49444945```4946494749484949### timestamp.get\_minute49504951Supported in:49524953[Rules](/chronicle/docs/detection/default-rules)4954[Search](/chronicle/docs/investigation/udm-search)49554956```4957timestamp.get_minute(unix_seconds [, time_zone])49584959```49604961#### Description49624963This function returns an integer in the range `[0, 59]` representing the minute.49644965* `unix_seconds` is an integer representing the number of seconds past Unix4966 epoch, such as `$e.metadata.event_timestamp.seconds`, or a placeholder4967 containing that value.4968* `time_zone` is optional and is a string representing a time zone. If4969 omitted, the default is "GMT". You can specify time zones using string4970 literals. The options are:4971 + The TZ database name, for example "America/Los\_Angeles". For more4972 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".49754976Here are examples of valid `time_zone` specifiers, which you can pass as the second argument to time extraction functions:49774978```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"49844985```49864987#### Param data types49884989`INT`, `STRING`49904991#### Return type49924993`INT`49944995#### Code samples49964997##### Example 149984999In this example, the `time_zone` argument is omitted, so it defaults to "GMT".50005001```5002$ts = $e.metadata.collected_timestamp.seconds50035004timestamp.get_hour($ts) = 1550055006```50075008##### Example 250095010This example uses a string literal to define the `time_zone`.50115012```5013$ts = $e.metadata.collected_timestamp.seconds50145015timestamp.get_hour($ts, "America/Los_Angeles") = 1550165017```5018501950205021### timestamp.get\_hour50225023Supported in:50245025[Rules](/chronicle/docs/detection/default-rules)5026[Search](/chronicle/docs/investigation/udm-search)50275028```5029timestamp.get_hour(unix_seconds [, time_zone])50305031```50325033#### Description50345035This function returns an integer in the range `[0, 23]` representing the hour.50365037* `unix_seconds` is an integer representing the number of seconds past Unix5038 epoch, such as `$e.metadata.event_timestamp.seconds`, or a placeholder5039 containing that value.5040* `time_zone` is optional and is a string representing a time zone. If5041 omitted, the default is "GMT". You can specify time zones using string5042 literals. The options are:5043 + The TZ database name, for example "America/Los\_Angeles". For more5044 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".50475048Here are examples of valid `time_zone` specifiers, which you can pass as the second argument to time extraction functions:50495050```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"50565057```50585059#### Param data types50605061`INT`, `STRING`50625063#### Return type50645065`INT`50665067#### Code samples50685069##### Example 150705071In this example, the `time_zone` argument is omitted, so it defaults to "GMT".50725073```5074$ts = $e.metadata.collected_timestamp.seconds50755076timestamp.get_hour($ts) = 1550775078```50795080##### Example 250815082This example uses a string literal to define the `time_zone`.50835084```5085$ts = $e.metadata.collected_timestamp.seconds50865087timestamp.get_hour($ts, "America/Los_Angeles") = 1550885089```5090509150925093### timestamp.get\_day\_of\_week50945095Supported in:50965097[Rules](/chronicle/docs/detection/default-rules)5098[Search](/chronicle/docs/investigation/udm-search)50995100```5101timestamp.get_day_of_week(unix_seconds [, time_zone])51025103```51045105#### Description51065107This function returns an integer in the range `[1, 7]` representing the day of5108week starting with Sunday. For example, 1 = Sunday and 2 = Monday.51095110* `unix_seconds` is an integer representing the number of seconds past Unix5111 epoch, such as `$e.metadata.event_timestamp.seconds`, or a placeholder5112 containing that value.5113* `time_zone` is optional and is a string representing a time\_zone. If5114 omitted, the default is "GMT". You can specify time zones using string5115 literals. The options are:5116 + The TZ database name, for example "America/Los\_Angeles". For more5117 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".51205121Here are examples of valid time\_zone specifiers, which you can pass as the second argument to time extraction functions:51225123```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"51295130```51315132#### Param data types51335134`INT`, `STRING`51355136#### Return type51375138`INT`51395140#### Code samples51415142##### Example 151435144In this example, the `time_zone` argument is omitted, so it defaults to "GMT".51455146```5147$ts = $e.metadata.collected_timestamp.seconds51485149timestamp.get_day_of_week($ts) = 651505151```51525153##### Example 251545155This example uses a string literal to define the `time_zone`.51565157```5158$ts = $e.metadata.collected_timestamp.seconds51595160timestamp.get_day_of_week($ts, "America/Los_Angeles") = 651615162```5163516451655166### timestamp.get\_timestamp51675168Supported in:51695170[Rules](/chronicle/docs/detection/default-rules)5171[Search](/chronicle/docs/investigation/udm-search)51725173```5174timestamp.get_timestamp(unix_seconds, optional timestamp_format/time_granularity, optional timezone)51755176```51775178#### Description51795180This function returns a string in the format `YYYY-MM-DD`, representing the day a timestamp is in.51815182* `unix_seconds` is an integer representing the number of seconds past Unix5183 epoch, such as `$e.metadata.event_timestamp.seconds`, or a placeholder5184 containing that value.5185* `timestamp_format` is optional and is a string representing the format for the5186 timestamp. If omitted, the default is `%F %T`. You can specify the format5187 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. If5191 omitted, the default is `GMT`. You can specify time zones using string5192 literals. The options are as follows:5193 + The IANA Time Zone (TZ) database name, for example, `America/Los_Angeles`. For more5194 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".51975198Here are examples of valid `time_zone` specifiers, which you can pass as the second argument to time extraction functions:51995200```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"52065207```52085209#### Param data types52105211`INT`, `STRING`, `STRING`52125213#### Return type52145215`STRING`52165217#### Code samples52185219##### Example 152205221In this example, the `time_zone` argument is omitted, so it defaults to `GMT`.52225223```5224$ts = $e.metadata.collected_timestamp.seconds52255226timestamp.get_timestamp($ts) = "2024-02-22 10:43:51"52275228```52295230##### Example 252315232This example uses a string literal to define the `time_zone`.52335234```5235$ts = $e.metadata.collected_timestamp.seconds52365237timestamp.get_timestamp($ts, "%F %T", "America/Los_Angeles") = "2024-02-22 10:43:51"52385239```52405241##### Example 352425243This example uses a string literal to define the `timestamp_format`.52445245```5246$ts = $e.metadata.collected_timestamp.seconds52475248timestamp.get_timestamp($ts, "%Y-%m", "GMT") = "2024-02"52495250```52515252##### Example 452535254This example formats a unix timestamp as a string at second granularity.52555256```5257timestamp.get_timestamp(1708598631, "SECOND", "GMT") = "2024-02-22 10:43:51"52585259```52605261##### Example 552625263This example formats a unix timestamp as a string at minute granularity.52645265```5266timestamp.get_timestamp(1708598631, "MINUTE", "GMT") = "2024-02-22 10:43"52675268```52695270##### Example 652715272This example formats a unix timestamp as a string at hour granularity.52735274```5275timestamp.get_timestamp(1708598631, "HOUR", "GMT") = "2024-02-22 10"52765277```52785279##### Example 752805281This example formats a unix timestamp as a string at day granularity.52825283```5284timestamp.get_timestamp(1708598631, "DATE", "GMT") = "2024-02-22"52855286```52875288##### Example 852895290This example formats a unix timestamp as a string at week granularity.52915292```5293timestamp.get_timestamp(1708598631, "WEEK", "GMT") = "2024-02-18"52945295```52965297##### Example 952985299This example formats a unix timestamp as a string at month granularity.53005301```5302timestamp.get_timestamp(1708598631, "MONTH", "GMT") = "2024-02"53035304```53055306##### Example 1053075308This example formats a unix timestamp as a string at year granularity.53095310```5311timestamp.get_timestamp(1708598631, "YEAR", "GMT") = "2024"53125313```5314531553165317### timestamp.get\_week53185319Supported in:53205321[Rules](/chronicle/docs/detection/default-rules)5322[Search](/chronicle/docs/investigation/udm-search)53235324```5325timestamp.get_week(unix_seconds [, time_zone])53265327```53285329#### Description53305331This function returns an integer in the range `[0, 53]` representing the week of5332the year. Weeks begin with Sunday. Dates before the first Sunday of the year are5333in week 0.53345335* `unix_seconds` is an integer representing the number of seconds past Unix5336 epoch, such as `$e.metadata.event_timestamp.seconds`, or a placeholder5337 containing that value.5338* `time_zone` is optional and is a string representing a time zone. If5339 omitted, the default is "GMT". You can specify time zones using string5340 literals. The options are:5341 + The TZ database name, for example "America/Los\_Angeles". For more5342 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".53455346Here are examples of valid `time_zone` specifiers, which you can pass as the second argument to time extraction functions:53475348```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"53545355```53565357#### Param data types53585359`INT`, `STRING`53605361#### Return type53625363`INT`53645365#### Code samples53665367##### Example 153685369In this example, the `time_zone` argument is omitted, so it defaults to "GMT".53705371```5372$ts = $e.metadata.collected_timestamp.seconds53735374timestamp.get_week($ts) = 053755376```53775378##### Example 253795380This example uses a string literal to define the `time_zone`.53815382```5383$ts = $e.metadata.collected_timestamp.seconds53845385timestamp.get_week($ts, "America/Los_Angeles") = 053865387```5388538953905391### timestamp.now53925393Supported in:53945395[Rules](/chronicle/docs/detection/default-rules)5396[Search](/chronicle/docs/investigation/udm-search)53975398```5399timestamp.now()54005401```54025403#### Description54045405Returns the number of seconds since 1970-01-01 00:00:00 UTC. This is also5406known as *Unix epoch time*.54075408#### Return type54095410`INT`54115412#### Code samples54135414##### Example 154155416The following example returns a timestamp for code executed on5417May 22, 2024 at 18:16:59.54185419```5420timestamp.now() = 1716401819 // Unix epoch time in seconds for May 22, 2024 at 18:16:5954215422```5423542454255426### window.avg54275428Supported in:54295430[Rules](/chronicle/docs/detection/default-rules)54315432```5433window.avg(numeric_values [, should_ignore_zero_values])54345435```54365437#### Description54385439Returns the average of the input values (which can be Integers or Floats). Setting the optional second argument to true ignores zero values.54405441#### Param data types54425443`INT|FLOAT`54445445#### Return type54465447`FLOAT`54485449#### Code samples54505451##### Example 154525453This example shows the integer average.54545455```5456// This rule sets the outcome $size_mode to the average5457// file size in the 5 minute match window.5458events:5459 $e.user.userid = $userid5460match:5461 $userid over 5m5462outcome: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 454645465```54665467##### Example 254685469This example shows the float average.54705471```5472events:5473 $e.user.userid = $userid5474match:5475 $userid over 5m5476outcome: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.454785479```54805481##### Example 354825483Negative input average54845485```5486events:5487 $e.user.userid = $userid5488match:5489 $userid over 5m5490outcome: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.454925493```54945495##### Example 4549654970 returns 054985499```5500events:5501 $e.user.userid = $userid5502match:5503 $userid over 5m5504outcome:5505 $size_mode = window.avg($e.file.size) // yields 0 if the event file size values in the match window is 055065507```55085509##### Example 555105511Ignoring 0 values55125513```5514events:5515 $e.user.userid = $userid5516match:5517 $userid over 5m5518outcome: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 39455205521```5522552355245525### window.first55265527Supported in:55285529[Rules](/chronicle/docs/detection/default-rules)55305531```5532window.first(values_to_sort_by, values_to_return)55335534```55355536#### Description55375538This 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).55395540#### Param data types55415542`INT`, `STRING`55435544#### Return type55455546`STRING`55475548#### Code samples55495550Get a string value derived from an event with the lowest correlated int value in the match window.55515552```5553// This rule sets the outcome $first_event to the lowest correlated int value5554// in the 5 minute match window.5555events:5556 $e.user.userid = $userid5557match:5558 $userid over 5m5559outcome: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.55615562```5563556455655566### window.last55675568Supported in:55695570[Rules](/chronicle/docs/detection/default-rules)55715572```5573window.last(values_to_sort_by, values_to_return)55745575```55765577#### Description55785579This 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).55805581#### Param data types55825583`INT`, `STRING`55845585#### Return type55865587`STRING`55885589#### Code samples55905591Get a string value derived from an event with the highest correlated int value in the match window.55925593```5594// This rule sets the outcome $last_event to the highest correlated int value5595// in the 5 minute match window.5596events:5597 $e.user.userid = $userid5598match:5599 $userid over 5m5600outcome: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.56025603```5604560556065607### window.median56085609Supported in:56105611[Rules](/chronicle/docs/detection/default-rules)56125613```5614window.median(numeric_values, should_ignore_zero_values)56155616```56175618#### Description56195620Return the median of the input values. If there are 2 median values, only 1 will be non-deterministically chosen as the return value.56215622#### Param data types56235624`INT|FLOAT`, `BOOL`56255626#### Return type56275628`FLOAT`56295630#### Code samples56315632##### Example 156335634This example returns the median when the input values aren't zero.56355636```5637rule median_file_size {5638 meta:5639 events:5640 $e.metadata.event_type = "FILE_COPY"5641 $userid = $e.principal.user.userid5642 match:5643 $userid over 1h5644 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 $e5648}56495650```56515652##### Example 256535654This example returns the median when the input includes some zero values that shouldn't be ignored.56555656```5657rule median_file_size {5658 meta:5659 events:5660 $e.metadata.event_type = "FILE_COPY"5661 $userid = $e.principal.user.userid5662 match:5663 $userid over 1h5664 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 $e5668}56695670```56715672##### Example 356735674This example returns the median when the input includes some zero values which should be ignored.56755676```5677rule median_file_size {5678 meta:5679 events:5680 $e.metadata.event_type = "FILE_COPY"5681 $userid = $e.principal.user.userid5682 match:5683 $userid over 1h5684 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 $e5688}56895690```56915692##### Example 456935694This example returns the median when the input includes all zero values which should be ignored.56955696```5697rule median_file_size {5698 meta:5699 events:5700 $e.metadata.event_type = "FILE_COPY"5701 $userid = $e.principal.user.userid5702 match:5703 $userid over 1h5704 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 $e5708}57095710```57115712##### Example 557135714This example shows that, when there are multiple medians, only one median is returned.57155716```5717rule median_file_size {5718 meta:5719 events:5720 $e.metadata.event_type = "FILE_COPY"5721 $userid = $e.principal.user.userid5722 match:5723 $userid over 1h5724 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 $e5728}57295730```5731573257335734### window.mode57355736Supported in:57375738[Rules](/chronicle/docs/detection/default-rules)57395740```5741window.mode(values)57425743```57445745#### Description57465747Return 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.57485749#### Param data types57505751`INT|FLOAT|STRING`57525753#### Return type57545755`STRING`57565757#### Code samples57585759##### Example 157605761Get mode of the values in the match window.57625763```5764// This rule sets the outcome $size_mode to the most frequently occurring5765// file size in the 5 minute match window.5766events:5767 $e.user.userid = $userid5768match:5769 $userid over 5m5770outcome: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.657725773```5774577557765777### window.stddev57785779Supported in:57805781[Rules](/chronicle/docs/detection/default-rules)57825783```5784window.stddev(numeric_values)57855786```57875788#### Description57895790Returns the standard deviation of input values in a match window.57915792#### Param data types57935794`INT|FLOAT`57955796#### Return type57975798`FLOAT`57995800#### Code samples58015802##### Example 158035804This example returns the standard deviation of integers in a match window.58055806```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 = $userid5810match:5811 $userid over 5m5812outcome: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 > 258165817```58185819##### Example 258205821This example returns the standard deviation of floats in a match window.58225823```5824events:5825 $e.user.userid = $userid5826match:5827 $userid over 5m5828outcome: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 > 258325833```58345835##### Example 358365837This example returns the standard deviation in a match window that contains negative numbers.58385839```5840events:5841 $e.user.userid = $userid5842match:5843 $userid over 5m5844outcome: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 > 258485849```58505851##### Example 458525853This example returns with zero standard deviation when all values in the match window are the same.58545855```5856events:5857 $e.user.userid = $userid5858match:5859 $userid over 5m5860outcome: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 > 258645865```58665867##### Example 558685869This example returns the standard deviation of a match window containing positive and negative numbers.58705871```5872events:5873 $e.user.userid = $userid5874match:5875 $userid over 5m5876outcome: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 > 1058805881```5882588358845885### window.variance58865887Supported in:58885889[Rules](/chronicle/docs/detection/default-rules)58905891```5892window.variance(values)58935894```58955896#### Description58975898This function returns the specified variance of the input values.58995900#### Param data types59015902`INT|FLOAT`59035904#### Return type59055906`FLOAT`59075908#### Code samples59095910##### Example 159115912This example returns the variance of all integers.59135914```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 = $userid5918match:5919 $userid over 5m5920outcome: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 > 1059245925```59265927##### Example 259285929This example returns the variance of all floats.59305931```5932events:5933 $e.user.userid = $userid5934match:5935 $userid over 5m5936outcome: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 > 1059405941```59425943##### Example 359445945This example returns the variance of negative numbers.59465947```5948events:5949 $e.user.userid = $userid5950match:5951 $userid over 5m5952outcome: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 > 1059565957```59585959##### Example 459605961This example returns a small variance value.59625963```5964events:5965 $e.user.userid = $userid5966match:5967 $userid over 5m5968outcome: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 > 1059725973```59745975##### Example 559765977This example returns a zero variance.59785979```5980events:5981 $e.user.userid = $userid5982match:5983 $userid over 5m5984outcome: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 > 1059885989```59905991##### Example 659925993This example returns the variance of positive and negative numbers.59945995```5996events:5997 $e.user.userid = $userid5998match:5999 $userid over 5m6000outcome: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 > 1060046005```6006600760086009### bytes.to\_base6460106011Supported in:60126013[Rules](/chronicle/docs/detection/default-rules)6014[Search](/chronicle/docs/investigation/udm-search)60156016```6017bytes.to_base64(bytes, optional_default_string)60186019```60206021#### Description60226023Function converts a `bytes` value to a `base64 encoded string`. Function calls with values that cannot be casted return an empty string by default.60246025#### Param data types60266027`BYTES`, `STRING`60286029#### Return type60306031`STRING`60326033#### Code samples60346035##### Raw Binary Bytes to Base64 Encoded String60366037The function converts the raw binary bytes to base64 encoded string.60386039```6040bytes.to_base64(b'000000006f8ec5586d026f9ddac56e9f2fe15b8a0000000001000000cd000000) = "AAAAAG+OxVhtAm+d2sVuny/hW4oAAAAAAQAAAM0AAAA="60416042```60436044##### Failed Conversion (Defaults to the Optionally Provided String)60456046The function defaults to the `"invalid bytes"` when the bytes value provided isn't valid.60476048```6049bytes.to_base64(b'000000006f8ec5586d", "invalid bytes") = "invalid bytes"60506051```60526053## Function to placeholder assignment60546055You can assign the result of a function call to a placeholder in the `events` section. For example:60566057`$placeholder = strings.concat($e.principal.hostname, "my-string").`60586059You can then use the placeholder variables in the `match`, `condition`, and `outcome` sections.6060However, there are two limitations with function to placeholder assignment:606160621. Every placeholder in function to placeholder assignment must be assigned to an expression containing an event field. For example, the following examples are valid:60636064```6065 $ph1 = $e.principal.hostname6066 $ph2 = $e.src.hostname60676068 // Both $ph1 and $ph2 have been assigned to an expression containing an event field.6069 $ph1 = strings.concat($ph2, ".com")60706071```60726073```6074 $ph1 = $e.network.email.from6075 $ph2 = strings.concat($e.principal.hostname, "@gmail.com")60766077 // Both $ph1 and $ph2 have been assigned to an expression containing an event field.6078 $ph1 = strings.to_lower($ph2)60796080```60816082 However, the following example is invalid:60836084```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.60876088```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:60926093 `$ph = strings.concat($event.principal.hostname, "string2")`60946095 `$ph = strings.concat($event.principal.hostname, $event.src.hostname)`60966097 However, the following is invalid:60986099 `$ph = strings.concat("string1", "string2")`61006101 `$ph = strings.concat($event.principal.hostname, $anotherEvent.src.hostname)`61026103## Reference Lists syntax61046105See our [page on Reference Lists](https://cloud.google.com/chronicle/docs/reference/reference-lists.md) for more information on6106reference list behavior and reference list syntax.61076108You can use reference lists in the `events` or `outcome` sections. Here is the6109syntax for using various types of reference lists in a rule:61106111```6112// STRING reference list6113$e.principal.hostname in %string_reference_list61146115// REGEX reference list6116$e.principal.hostname in regex %regex_reference_list61176118// CIDR reference list6119$e.principal.ip in cidr %cidr_reference_list612061216122```61236124You can also use the `not` operator and the `nocase` operator with reference lists as shown in the following example:61256126```6127// Exclude events whose hostnames match substrings in my_regex_list.6128not $e.principal.hostname in regex %my_regex_list61296130// Event hostnames must match at least 1 string in my_string_list (case insensitive).6131$e.principal.hostname in %my_string_list nocase61326133```61346135The `nocase` operator is compatible with `STRING` lists and `REGEX` lists.61366137For performance reasons, the Detection Engine restricts reference list usage.61386139* Maximum `in` statements in a rule, with or without special operators: 76140* Maximum `in` statements with the `regex` operator: 46141* Maximum `in` statements with the `cidr` operator: 261426143## Type checking61446145Google 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.61466147The following are examples of **invalid** predicates:61486149```6150// $e.target.port is of type integer which cannot be compared to a string.6151$e.target.port = "80"61526153// "LOGIN" is not a valid event_type enum value.6154$e.metadata.event_type = "LOGIN"61556156```61576158## Detection Event Sampling61596160Detections from multi-event rules contain event samples to provide context6161about the events that caused the detection. There is a limit of up to 10 event6162samples for each event variable defined in the rule. For example, if a rule6163defines 2 event variables, each detection can have up to 20 event samples. The6164limit applies to each event variable separately. If one event variable has61652 applicable events in this detection, and the other event variable has 156166applicable events, the resulting detection contains 12 event samples (2 + 10).61676168Any event samples over the limit are omitted from the detection.61696170If 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.61736174If you are viewing detections in the UI, you can download all events samples6175for a detection. For more information, see [Download events](/chronicle/docs/detection/downloading-events).61766177Last updated 2025-06-08 UTC.6178
Also in repulsivityy/elevate_2025
Diff this repo’s formatsOne 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?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| repulsivityy/elevate_2025.clinerules/OVERVIEW_OF_YARAL_LANGUAGE.md · 2 | Cline rules | archdo-not | 45/100 | 3 days ago | |
| repulsivityy/elevate_2025.clinerules/YARA_RULES_STYLE_GUIDE.md · 2 | Cline rules | buildstylearchtypes | 46/100 | 3 days ago | |
| repulsivityy/elevate_2025ai-runbooks-elevate25/.clinerules/suggested_mcp_tools.md · 2 | Cline rules | no sections | 34/100 | 3 days ago | |
| repulsivityy/elevate_2025.clinerules/SECOPS_YARAL_STYLE_GUIDE.md · 2 | Cline rules | lint-formatstyledo-not | 61/100 | 3 days ago | |
| repulsivityy/elevate_2025.clinerules/coding_conventions.md · 2 | Cline rules | styledocs | 34/100 | 3 days ago | |
| repulsivityy/elevate_2025.clinerules/project_plan.md · 2 | Cline rules | agent-behaviour | 26/100 | 3 days ago | |
| repulsivityy/elevate_2025.clinerules/readme.md · 2 | Cline rules | setuparch | 52/100 | 3 days ago | |
| repulsivityy/elevate_2025.clinerules/reporting_templates.md · 2 | Cline rules | typessecurity | 44/100 | 3 days ago | |
| repulsivityy/elevate_2025.clinerules/suggested_mcp_tools.md · 2 | Cline rules | no sections | 34/100 | 3 days ago | |
| repulsivityy/elevate_2025ai-runbooks-elevate25/.clinerules/coding_conventions.md · 2 | Cline rules | styledocs | 34/100 | 3 days ago | |
| repulsivityy/elevate_2025ai-runbooks-elevate25/.clinerules/project_plan.md · 2 | Cline rules | agent-behaviour | 26/100 | 3 days ago | |
| repulsivityy/elevate_2025ai-runbooks-elevate25/.clinerules/readme.md · 2 | Cline rules | setuparch | 52/100 | 3 days ago | |
| repulsivityy/elevate_2025ai-runbooks-elevate25/.clinerules/reporting_templates.md · 2 | Cline rules | typessecurity | 44/100 | 3 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.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| bashdeban/fastmind.clinerules/.project-consistency-keeper2.md · 5 | Cline rules | setupbuildtestlint-format+11 | 100/100 | 3 days ago | |
| JCodesMore/ai-website-cloner-template.clinerules · 31k | Cline rules | buildlint-formatstylearch+3 | 97/100 | 2 days ago | |
| BryaanF/LiantPortfolio.clinerules/project-guidelines.md · 0 | Cline rules | buildstylearchgit+2 | 96/100 | 3 days ago | |
| u9401066/zotero-keeper.clinerules/50-pubmed-project.md · 6 | Cline rules | testlint-formatstylearch+1 | 94/100 | 3 days ago | |
| u9401066/zotero-keepervscode-extension/resources/repo-assets/pubmed-search-mcp/.clinerules/50-pubmed-project.md · 6 | Cline rules | testlint-formatstylearch+1 | 94/100 | 3 days ago | |
| u9401066/pubmed-search-mcp.clinerules/50-pubmed-project.md · 23 | Cline rules | testlint-formatstylearch+1 | 94/100 | 3 days ago | |
| HerringtonDarkholme/megarepo.clinerules/02-development.md · 17 | Cline rules | setupbuildteststyle+3 | 92/100 | 3 days ago | |
| blendsdk/codeops-mcp.clinerules/project.md · 0 | Cline rules | buildteststylearch+7 | 91/100 | 3 days ago |
