From 8489b95c054410e80d82674252e0bd442ce0c42f Mon Sep 17 00:00:00 2001 From: eric-forte-elastic Date: Mon, 24 Nov 2025 10:53:23 -0500 Subject: [PATCH 1/3] Updated regex pattern for multiline --- detection_rules/schemas/definitions.py | 4 +++- pyproject.toml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/detection_rules/schemas/definitions.py b/detection_rules/schemas/definitions.py index 762e9786b18..9a5b813abff 100644 --- a/detection_rules/schemas/definitions.py +++ b/detection_rules/schemas/definitions.py @@ -76,7 +76,9 @@ def validator_wrapper(value: Any) -> Any: CONDITION_VERSION_PATTERN = re.compile(rf"^\^{_version}$") VERSION_PATTERN = f"^{_version}$" MINOR_SEMVER = re.compile(r"^\d+\.\d+$") -FROM_SOURCES_REGEX = re.compile(r"^\s*FROM\s+(?P.+?)\s*(?:\||\bmetadata\b|//|$)", re.IGNORECASE | re.MULTILINE) +FROM_SOURCES_REGEX = re.compile( + r"^\s*FROM\s+(?P(?:.+?(?:,\s*)?\n?)+?)\s*(?:\||\bmetadata\b|//|$)", re.IGNORECASE | re.MULTILINE +) BRANCH_PATTERN = f"{VERSION_PATTERN}|^master$" ELASTICSEARCH_EQL_FEATURES = { "allow_negation": (Version.parse("8.9.0"), None), diff --git a/pyproject.toml b/pyproject.toml index b8467f2c839..c37ce537f4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "detection_rules" -version = "1.5.14" +version = "1.5.15" 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" From db499c28b3eb74df188bd5ddb7e78f1feaef74a3 Mon Sep 17 00:00:00 2001 From: eric-forte-elastic Date: Wed, 3 Dec 2025 10:59:57 -0500 Subject: [PATCH 2/3] Add line split unit test --- tests/test_rules_remote.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/test_rules_remote.py b/tests/test_rules_remote.py index e74d9631acd..28aa7abeaf4 100644 --- a/tests/test_rules_remote.py +++ b/tests/test_rules_remote.py @@ -155,6 +155,23 @@ def test_esql_filtered_index_error(self): with pytest.raises(EsqlSchemaError): _ = RuleCollection().load_dict(production_rule) + def test_new_line_split_index(self): + """Test an ESQL rule's index validation to ensure that it can handle new line split indices.""" + file_path = get_path(["tests", "data", "command_control_dummy_production_rule.toml"]) + original_production_rule = load_rule_contents(file_path) + # Test that a ValidationError is raised if the query doesn't match the schema + production_rule = deepcopy(original_production_rule)[0] + production_rule["metadata"]["integration"] = ["aws"] + production_rule["rule"]["query"] = """ + from logs-aws.cloud*, logs-network_traffic.http-*, + logs-nginx.access-* metadata _id, _version, _index + | where @timestamp > now() - 30 minutes + and aws.cloudtrail.user_identity.type == "IAMUser" + | keep + aws.* + """ + _ = RuleCollection().load_dict(production_rule) + def test_esql_endpoint_alerts_index(self): """Test an ESQL rule's schema validation using ecs fields in the alerts index.""" file_path = get_path(["tests", "data", "command_control_dummy_production_rule.toml"]) From 39847441c19385e1d069327c62deec3d1e02fead Mon Sep 17 00:00:00 2001 From: eric-forte-elastic Date: Wed, 3 Dec 2025 11:05:38 -0500 Subject: [PATCH 3/3] Remove comment --- tests/test_rules_remote.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_rules_remote.py b/tests/test_rules_remote.py index 28aa7abeaf4..507654411fb 100644 --- a/tests/test_rules_remote.py +++ b/tests/test_rules_remote.py @@ -159,7 +159,6 @@ def test_new_line_split_index(self): """Test an ESQL rule's index validation to ensure that it can handle new line split indices.""" file_path = get_path(["tests", "data", "command_control_dummy_production_rule.toml"]) original_production_rule = load_rule_contents(file_path) - # Test that a ValidationError is raised if the query doesn't match the schema production_rule = deepcopy(original_production_rule)[0] production_rule["metadata"]["integration"] = ["aws"] production_rule["rule"]["query"] = """