From d252cae4ee1f4894a0a114c9367fde19d60f2802 Mon Sep 17 00:00:00 2001 From: Eric Forte <119343520+eric-forte-elastic@users.noreply.github.com> Date: Tue, 27 Jan 2026 23:01:27 -0500 Subject: [PATCH] Ignore Keep * for ES|QL hash calc (#5638) * Ignore Keep * for ES|QL hash calc Co-authored-by: Mika Ayenson, PhD --------- Co-authored-by: Mika Ayenson, PhD --- detection_rules/rule.py | 21 +++++++++++++++++++++ pyproject.toml | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/detection_rules/rule.py b/detection_rules/rule.py index f9d2a48b6..2239c9031 100644 --- a/detection_rules/rule.py +++ b/detection_rules/rule.py @@ -1259,6 +1259,22 @@ class BaseRuleContents(ABC): return obj + def _uses_keep_star(self, hashable_dict: dict[str, Any]) -> bool: + """Check if this is an ES|QL rule that uses `| keep *`.""" + if hashable_dict.get("language") != "esql": + return False + + query: str | None = hashable_dict.get("query") + if not isinstance(query, str) or not query: + return False + + keep_pattern = re.compile(r"\|\s*keep\b\s+([^\|]+)", re.IGNORECASE | re.DOTALL) + keep_match: re.Match[str] | None = keep_pattern.search(query) + if keep_match: + keep_fields: list[str] = [field.strip() for field in keep_match.group(1).split(",")] + return "*" in keep_fields + return False + @abstractmethod def to_api_format(self, include_version: bool = True) -> dict[str, Any]: """Convert the rule to the API format.""" @@ -1273,6 +1289,11 @@ class BaseRuleContents(ABC): if not include_integrations: hashable_dict.pop("related_integrations", None) + # For ES|QL rules with `| keep *`, exclude required_fields since they're + # non-deterministic (depend on integration schemas which vary by stack version) + if self._uses_keep_star(hashable_dict): + hashable_dict.pop("required_fields", None) + return hashable_dict @cached diff --git a/pyproject.toml b/pyproject.toml index 9ab13ce35..a64f5db73 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "detection_rules" -version = "1.5.35" +version = "1.5.36" description = "Detection Rules is the home for rules used by Elastic Security. This repository is used for the development, maintenance, testing, validation, and release of rules for Elastic Security’s Detection Engine." readme = "README.md" requires-python = ">=3.12"