From 7445a6051028b110cccfd6560613bd083a3cfe54 Mon Sep 17 00:00:00 2001 From: Ricardo Valdes Date: Wed, 16 Sep 2026 20:34:18 -0400 Subject: [PATCH] fix: align SentinelOne filter and rule contracts --- filters/antivirus/sentinel-one.yml | 12 ++-- filters/audits/sentinelone.md | 40 +++++++++++ .../filter-contracts/sentinelone.json | 71 +++++++++++++++++++ 3 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 filters/audits/sentinelone.md create mode 100644 plugins/alerts/testdata/filter-contracts/sentinelone.json diff --git a/filters/antivirus/sentinel-one.yml b/filters/antivirus/sentinel-one.yml index e1cf94824..9c19ae9eb 100644 --- a/filters/antivirus/sentinel-one.yml +++ b/filters/antivirus/sentinel-one.yml @@ -368,20 +368,20 @@ pipeline: function: string params: key: actionResult - value: "failed" - where: 'equals("log.threatStatus", "mitigation_failed")' + value: failure + where: equals("log.threatStatus", "mitigation_failed") - add: function: string params: key: actionResult - value: "failed" - where: 'equals("log.status", "failed") && !exists("actionResult")' + value: failure + where: equals("log.status", "failed") && !exists("actionResult") - add: function: string params: key: actionResult - value: "failed" - where: 'contains("log.mitigationStatus", "fail") && !exists("actionResult")' + value: failure + where: contains("log.mitigationStatus", "fail") && !exists("actionResult") # Removing unused fields - delete: diff --git a/filters/audits/sentinelone.md b/filters/audits/sentinelone.md new file mode 100644 index 000000000..7fbe38131 --- /dev/null +++ b/filters/audits/sentinelone.md @@ -0,0 +1,40 @@ +# SentinelOne normalization and rule review + +Normalize mitigation and operation failures to actionResult=failure. + +This draft targets UTMStack `v11`. It contains 1 filter changes +and 0 rule changes for this technology only. Review covered +1 filter configurations and 19 matching shipped rule files. +Unchanged rules are listed in the regression manifest; they are not duplicated in the diff. + +## Contract and validation + +- Compared exact standard names/types with go-sdk v1.1.31 and the supplied UTMStack dictionaries. +- Checked documented pipeline ordering, rename/move behavior, open vendor log fields, + event-side versus alert-side fields, and surviving fields used by affected rule predicates/history/grouping. +- Strict SDK configuration decoding and actual CEL compilation pass for this scope. +- 3 synthetic normalization cases pass, including SDK Event conversion and any + trigger predicate assertions recorded in the manifest. +- The scoped alerts module tests and `git diff --check` pass with the shared contract runner applied. + +The shared alert-contract PR supplies the reusable Go runner for the manifest in +`plugins/alerts/testdata/filter-contracts/sentinelone.json`. Apply that support before running `go test ./...` in `plugins/alerts`. + +The model starts from synthetic extraction results. It does not run complex grok, +JSON/KV/XML/CSV extraction, time conversion, dynamic plugins, historical OpenSearch +queries, or the closed EventProcessor. Raw vendor logs and resulting alerts must +still be checked in staging before rollout. No customer false-positive reduction +has been measured and no production rollout is included. + + + +## References + +- [SDK schema](https://github.com/threatwinds/go-sdk/blob/v1.1.31/plugins/plugins.proto) +- [Filter steps](https://github.com/threatwinds/go-sdk/wiki/Filter-Steps-Reference) +- [Standard event schema](https://github.com/threatwinds/go-sdk/wiki/Standard-Event-Schema) +- [Rule implementation](https://github.com/threatwinds/go-sdk/wiki/Implementing-Rules) + +`afterEvents`, empty noncapturing grok names, supported numeric strings, and custom +`log.*` fields are accepted. Existing textual protocol casing and vendor action names +are preserved unless a concrete consumer mismatch requires correction. diff --git a/plugins/alerts/testdata/filter-contracts/sentinelone.json b/plugins/alerts/testdata/filter-contracts/sentinelone.json new file mode 100644 index 000000000..11dbe4acd --- /dev/null +++ b/plugins/alerts/testdata/filter-contracts/sentinelone.json @@ -0,0 +1,71 @@ +{ + "technology": "SentinelOne", + "filters": [ + "filters/antivirus/sentinel-one.yml" + ], + "rules": [ + "rules/antivirus/sentinel-one/agent_tampering_attempts.yml", + "rules/antivirus/sentinel-one/ai_based_threat_hunting_alerts.yml", + "rules/antivirus/sentinel-one/behavioral_threat_detection.yml", + "rules/antivirus/sentinel-one/cloud_workload_protection_alerts.yml", + "rules/antivirus/sentinel-one/container_security_alerts.yml", + "rules/antivirus/sentinel-one/custom_detection_rule_triggers.yml", + "rules/antivirus/sentinel-one/deep_visibility_threat_indicators.yml", + "rules/antivirus/sentinel-one/endpoint_detection_response_alerts.yml", + "rules/antivirus/sentinel-one/iot_device_compromise_indicators.yml", + "rules/antivirus/sentinel-one/kernel_level_threat.yml", + "rules/antivirus/sentinel-one/memory_injection_detection.yml", + "rules/antivirus/sentinel-one/rollback_operation_patterns.yml", + "rules/antivirus/sentinel-one/s1_exclusion_abuse.yml", + "rules/antivirus/sentinel-one/s1_policy_downgrade.yml", + "rules/antivirus/sentinel-one/storyline_correlation.yml", + "rules/antivirus/sentinel-one/suspicious_process_tree.yml", + "rules/antivirus/sentinel-one/suspicious_script_execution.yml", + "rules/antivirus/sentinel-one/threat_intelligence_matches.yml", + "rules/antivirus/sentinel-one/threat_mitigation_failures.yml" + ], + "fixtures": [ + { + "name": "sentinel_failure_threatStatus", + "filter": "antivirus/sentinel-one.yml", + "input": { + "log": { + "threatStatus": "mitigation_failed" + } + }, + "expected": { + "actionResult": "failure" + }, + "absent": [], + "rules": {} + }, + { + "name": "sentinel_failure_status", + "filter": "antivirus/sentinel-one.yml", + "input": { + "log": { + "status": "failed" + } + }, + "expected": { + "actionResult": "failure" + }, + "absent": [], + "rules": {} + }, + { + "name": "sentinel_failure_mitigationStatus", + "filter": "antivirus/sentinel-one.yml", + "input": { + "log": { + "mitigationStatus": "failed" + } + }, + "expected": { + "actionResult": "failure" + }, + "absent": [], + "rules": {} + } + ] +}