Skip to content

Commit 97dbd29

Browse files
authored
Align correlation-rule hydration with documented filter and clarify Event Query vs Get Detection Details (#29)
Two refinements to the correlation-rule guidance. First, the multi-record filter now matches the pattern in the official Fusion detection-email documentation: drop the correlation meta-event and keep the underlying events with `| xdr_type != correlation-rule-detection | report_name != *`, rather than the inferred `#event.kind`/`Ngsiem.event.product` filters. Second, the choice between Event Query and Get Detection Details is reframed as a data-granularity decision, not a reliability one: Event Query reaches the event-level detail (per-event source IP, country, and so on) that composed the detection, while Get Detection Details returns the detection object's summary fields. Use whichever matches the data you actually need. Updated event-query-vs-api.md, both trigger-types.md copies, event-queries.md, ngsiem-detection-response.md, and the validate.py guard message. 541 tests pass; pylint and markdownlint clean.
1 parent a8ece4b commit 97dbd29

6 files changed

Lines changed: 52 additions & 34 deletions

File tree

skills/authoring/references/event-query-vs-api.md

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,24 @@ silently return zero. The split is about whether you already hold the object:
8383
8484
- **Correlation-rule detections** → hydrate with the same
8585
`Ngsiem.alert.id = ?detectID` query. It works, but returns **multiple records**
86-
(the alert record plus the underlying events), so `results[0]` is
87-
non-deterministic across runs. Filter to a single predictable row with
88-
`| #event.kind = "event"` or `| Ngsiem.event.product = CrowdStrike`, or project
89-
named columns with `table([field1, field2, ...])`. Restrict the action's output
90-
schema to only the fields you read, so runs that omit some fields don't fail
91-
schema validation. If Event Query results are unreliable for your detection
92-
type, a **Get Detection Details** action (or a CrowdStrike HTTP Request to
93-
`/alerts/entities/alerts/v2` passing the composite `DetectionID` as
94-
`composite_id`) is a valid alternative.
86+
(the underlying events plus a correlation "meta-event" that only signals the
87+
rule fired), so `results[0]` is non-deterministic across runs. Drop the
88+
meta-event and keep the real events:
89+
90+
```
91+
Ngsiem.alert.id = ?detectID
92+
| xdr_type != correlation-rule-detection
93+
| report_name != *
94+
```
95+
96+
or project named columns with `table([field1, field2, ...])`. Restrict the
97+
action's output schema to only the fields you read, so runs that omit some
98+
fields don't fail schema validation. Event Query is how you reach the
99+
**event-level detail** (per-event source IP, country, and so on) that made up
100+
the detection. A **Get Detection Details** action returns the detection
101+
*object* instead — reach for it when the object's summary fields are all you
102+
need, or call `/alerts/entities/alerts/v2` with the composite `DetectionID` as
103+
`composite_id` for that same object.
95104
96105
**Treat detection IDs as opaque.** Per the detections team, `composite_id` (what
97106
the trigger hands you) is the primary key used to retrieve a detection, but its

skills/authoring/references/trigger-types.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -217,14 +217,16 @@ through an inline Python extractor** (`cs.json.decode(data['<Python>.output_stdo
217217
**Event Query hydration works for all NG-SIEM detection types** — match the
218218
composite `DetectionID` against `Ngsiem.alert.id` (not `Ngsiem.detection.id`).
219219
For **correlation-rule detections** the same `Ngsiem.alert.id = ?DetectionID`
220-
query works, but it returns **multiple records** (the alert record plus the
221-
underlying events), so `results[0]` is non-deterministic without a filter. Narrow
222-
it to one predictable row with `| #event.kind = "event"` or
223-
`| Ngsiem.event.product = CrowdStrike`, or project named columns with
224-
`table([field1, field2, ...])`. If Event Query results are unreliable for a given
225-
detection type, a **Get Detection Details** action (or an HTTP Request to
226-
`/alerts/entities/alerts/v2` passing the composite `DetectionID` as `composite_id`)
227-
is a valid alternative. See `references/event-query-vs-api.md`.
220+
query works, but it returns **multiple records** (the underlying events plus a
221+
correlation "meta-event" that only signals the rule fired), so `results[0]` is
222+
non-deterministic without a filter. Drop the meta-event and keep the real events
223+
with `| xdr_type != correlation-rule-detection | report_name != *`, or project
224+
named columns with `table([field1, field2, ...])`. Event Query is how you reach
225+
the event-level detail that composed the detection; a **Get Detection Details**
226+
action (or an HTTP Request to `/alerts/entities/alerts/v2` passing the composite
227+
`DetectionID` as `composite_id`) returns the detection object instead — use it when
228+
the object's summary fields are all you need. See
229+
`references/event-query-vs-api.md`.
228230

229231
**Not every `Trigger.Detection.*` field resolves on the NG-SIEM trigger.**
230232
`${Trigger.Detection.Product}` and `${Trigger.Detection.Description}` are available

skills/authoring/scripts/validate.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,8 +424,9 @@ def _check_detection_hydration_join(label, config, issues):
424424
f"that field. The trigger's composite DetectionID is stored in "
425425
f"'Ngsiem.alert.id' for all detection types — change the join field to "
426426
f"'Ngsiem.alert.id'. For correlation-rule detections that query returns "
427-
f"multiple records (the alert plus underlying events), so filter it "
428-
f"(e.g. '| #event.kind = \"event\"') to a single predictable row. As "
427+
f"multiple records (the underlying events plus a correlation meta-event), "
428+
f"so filter it (e.g. '| xdr_type != correlation-rule-detection | "
429+
f"report_name != *') to the real events. As "
429430
f"written this query returns zero rows at runtime and the workflow "
430431
f"enriches nothing, despite releasing cleanly. See "
431432
f"references/event-query-vs-api.md."

skills/workflows/references/trigger-types.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,15 @@ you do not need an Event Query to hydrate the detection.
126126
**If you must hydrate a detection** (indicators not on the trigger), match the
127127
composite `DetectionID` against `Ngsiem.alert.id` (not `Ngsiem.detection.id`) in
128128
an Event Query. This works for all NG-SIEM detection types. For **correlation-rule
129-
detections** the same query returns **multiple records** (the alert plus the
130-
underlying events), so filter it to one predictable row — `| #event.kind = "event"`
131-
or `| Ngsiem.event.product = CrowdStrike` — or project columns with `table([...])`.
132-
A **Get Detection Details** action (or an HTTP Request to
129+
detections** the same query returns **multiple records** (the underlying events
130+
plus a correlation "meta-event" that only signals the rule fired), so drop the
131+
meta-event and keep the real events —
132+
`| xdr_type != correlation-rule-detection | report_name != *` — or project columns
133+
with `table([...])`. Event Query is how you reach the event-level detail that made
134+
up the detection; a **Get Detection Details** action (or an HTTP Request to
133135
`/alerts/entities/alerts/v2` passing the composite `DetectionID` as `composite_id`)
134-
is a valid alternative if Event Query results are unreliable. See
135-
`../../authoring/references/event-query-vs-api.md`.
136+
returns the detection object instead — use it when the object's summary fields are
137+
all you need. See `../../authoring/references/event-query-vs-api.md`.
136138

137139
**Severity is an integer (1-5) at `Trigger.Detection.Severity`, not a string.** Use numeric comparison in CEL conditions:
138140

use-cases/event-queries.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,10 @@ code-driven querying belongs in a function.
111111
> and has its ID, an Event Query like `Ngsiem.alert.id = ?detectID` to pull more fields is the right
112112
> tool (match the composite `DetectionID` against `Ngsiem.alert.id`, not `Ngsiem.detection.id`).
113113
> **Correlation-rule detections can also be hydrated** with `Ngsiem.alert.id = ?detectID`, but the
114-
> query returns multiple records (the alert plus the underlying events), so `results[0]` is
115-
> non-deterministic without a filter. Narrow it with `| #event.kind = "event"` or
116-
> `| Ngsiem.event.product = CrowdStrike`, or project named columns with `table([...])`. A **Get
117-
> Detection Details** action remains a valid alternative if Event Query results are unreliable for
118-
> your detection type. See [event-query-vs-api.md](../skills/authoring/references/event-query-vs-api.md).
114+
> query returns multiple records (the underlying events plus a correlation "meta-event" that only
115+
> signals the rule fired), so `results[0]` is non-deterministic without a filter. Drop the meta-event
116+
> and keep the real events with `| xdr_type != correlation-rule-detection | report_name != *`, or
117+
> project named columns with `table([...])`. Event Query is how you reach the event-level detail that
118+
> composed the detection; a **Get Detection Details** action returns the detection object instead —
119+
> use it when the object's summary fields are all you need. See
120+
> [event-query-vs-api.md](../skills/authoring/references/event-query-vs-api.md).

use-cases/ngsiem-detection-response.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,12 @@ where each is covered in depth and verified live.
7979
- **Hydration join key is `Ngsiem.alert.id`, not `Ngsiem.detection.id`.** Match the
8080
composite `DetectionID` against `Ngsiem.alert.id` for all detection types. A
8181
correlation-rule detection hydrates the same way, but the query returns multiple
82-
records (the alert plus its underlying events), so filter to one predictable row
83-
(`| #event.kind = "event"` or `| Ngsiem.event.product = CrowdStrike`) — an
84-
unfiltered `results[0]` is the most common silent-empty/wrong-row failure. A Get
85-
Detection Details action is a valid fallback. See `references/event-query-vs-api.md`.
82+
records (the underlying events plus a correlation "meta-event" that only signals
83+
the rule fired), so drop the meta-event and keep the real events
84+
(`| xdr_type != correlation-rule-detection | report_name != *`) — an unfiltered
85+
`results[0]` is the most common silent-empty/wrong-row failure. Event Query is how
86+
you reach the event-level detail; a Get Detection Details action returns the
87+
detection object instead. See `references/event-query-vs-api.md`.
8688
- **Charlotte AI needs credits**, and the org must opt in. A workflow that invokes
8789
it will not produce a summary in a tenant without them.
8890
- **Business-hours logic:** the guide implements the time gate as hardcoded

0 commit comments

Comments
 (0)