Skip to content

fix(sentinel-one): set failure only from an explicit final status - #2679

Draft
kryonsx wants to merge 1 commit into
utmstack:v11from
kryonsx:codex/data-engine-antivirus-sentinel-one-20260923
Draft

kryonsx wants to merge 1 commit into
utmstack:v11from
kryonsx:codex/data-engine-antivirus-sentinel-one-20260923

Conversation

@kryonsx

@kryonsx kryonsx commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

Problem

The SentinelOne filter sets actionResult in three steps, all to failed: when log.threatStatus is mitigation_failed, when log.status is failed, or when log.mitigationStatus contains the substring fail. failed is not one of the standard outcome values (success, failure, denied) in the SDK standard event schema. The substring test also turns a value such as not_failed into a failure. The exact comparisons miss upper-case values such as FAILURE. A record that reports both a failed and a successful status is still labelled a failure.

Change

One step replaces the three. It sets failure only for an exact, case-insensitive failed status: threatStatus mitigation_failed, status failed, or mitigationStatus failed, failure or mitigation_failed. If the same record also reports success (mitigationStatus success, succeeded or mitigated, or status success or succeeded), the result stays unset. A successful remediation is not evidence that a connection was allowed, and console events carry no final result, so neither sets an outcome. Only the outcome block and the version comment change. The status keys are the ones this filter already used.

Validation

  • plugins/alerts/testdata/sentinel_one_action_result.json holds ten fabricated raw lines. They use the console CEF framing observed in real records, with invented values, example.com names and an RFC 5737 address. They cover each failed status, upper case, a composite value, contradictory statuses, a successful remediation, a console event, a console notification that carries a device address, and a non-CEF transport line. In an isolated EventProcessor parser (commit 497bf53, parser SDK v1.1.26, with the v11 shared grok patterns), the unchanged filter passed 4/10 of these cases and the corrected filter passed 10/10, with no event errors. The device address stays vendor detail: no case produced origin.ip or target.ip.
  • TestSentinelOneActionResultContract runs the filter's ordered outcome steps with this branch's go-sdk v1.1.33 CEL. It checks positive and negative equals("actionResult", …) predicates for all three standard values. The full plugins/alerts suite passes.
  • Read-only sampling covered every retained SentinelOne record on the only instance that holds this data type. They are console administration events, a synthetic load-test stream and a few manual test lines. None carries a threat, mitigation or status field, an outcome, or a standard IP. The filter deployed there matches the reviewed source. The isolated parser reproduced every stored field of 20 of those records with both the unchanged and the corrected filter, and left actionResult unset on all of them. Records and identifiers stay private.
  • No rule, shipped dashboard or history query reads SentinelOne's actionResult.

Compatibility

  • Draft fix(sentinel-one): parse CEF header and full values; align rule consumers #2677 rewrites this filter's CEF parsing and keeps the outcome block byte-identical. The two changes merge with a single conflict, on the version comment; resolve it to 3.1.0. The merged filter passed both PRs' Go tests, the full suite, and the same fabricated and replayed cases in the isolated parser.
  • This filter sets no standard IP, domain or host, so the change does not alter threat-intelligence matching for SentinelOne today. The shared TI outcome consumer has a separately tested draft correction that requires exact confirmed success. Review it with this source change before relying on canonical outcomes for TI alerts.

Limits

SentinelOne's syslog field reference could not be retrieved through the allowlisted documentation fetcher, and no threat or mitigation record was available. The status keys and values are therefore the existing filter's, not vendor-documented ones. The isolated parser links SDK v1.1.26 while the alerts module pins v1.1.33, so deployed behavior after rollout remains unverified. No customer configuration was changed and no production alert is claimed.

CI

The Go dependency check and prompt discovery passed. The three AI review jobs stopped at the required-secret check (THREATWINDS_API_KEY is not available to this fork's runners), so they reviewed no code, and the aggregate check reports that failure. The local regression results above are separate from those jobs.

🤖 Generated with Claude Code

The three actionResult steps wrote the nonstandard value `failed`, matched
`fail` as a substring of log.mitigationStatus, missed upper-case values and
labelled contradictory statuses as failures. One step now sets the standard
`failure` only for an exact, case-insensitive failed threat, operation or
mitigation status, and leaves the result unset when the same record also
reports success. Successful remediation and console events keep no outcome.

Adds ten fabricated raw lines in the observed console CEF framing and an
ordered-step CEL test with go-sdk v1.1.33.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant