Files
riposte-marketplace/integrations/crowdstrike/mappers/search_detections.yaml
T
f3nris 21b957be72 fix(crowdstrike): map severity and the MTTD anchor in search_detections (v1.2.4)
Two silent defects in the search_detections OCSF mapper.

Severity was a four-branch ternary that resolved to nothing, so every
ingested alert kept the alert rule's default severity instead of Falcon's
— a Low arrived as Medium and a Critical arrived as Medium too. It is now
a plain path to severity_name, whose words the ingestion engine reads
natively. (The ternary form is also repaired upstream, but a plain path is
simpler to read and to correct.)

No entry fed the OCSF `time` field, which is the only field the engine
reads to stamp detected_at. Incidents were anchored at ingestion instead
of at detection, so MTTD measured the collection delay as zero — over a
day on a slow poll. finding_info.created_time carries the same instant but
is read by nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-01 22:06:45 +02:00

65 lines
5.2 KiB
YAML

name: "CrowdStrike Falcon Alerts → OCSF"
description: "Exhaustive map of a CrowdStrike Falcon unified alert (alerts/entities/alerts/v2, results_path = resources) to OCSF. Field paths validated against the Falcon Raptor alert schema. Triggering process = actor (actor.*); detected file = subject (file.*); MITRE under attacks.*."
field_mappings:
title: "name"
# A plain path, not a ternary: the ingestion engine reads the words
# informational/low/medium/high/critical natively, so Falcon's severity_name
# needs no translation. This was a four-branch ternary that resolved to nothing
# and left every alert on the rule's default severity, whatever Falcon said.
severity: "severity_name"
description: "description"
# results_path = resources; source_path is JSONata over ONE alert object.
# Paths absent from a given alert are skipped at ingestion, so extra entries are safe.
ocsf:
# ── Endpoint / device ─────────────────────────────────────────────
- { source_path: "device.hostname", ocsf_field: "src_endpoint.hostname" }
- { source_path: "device.hostinfo.domain", ocsf_field: "src_endpoint.domain" }
- { source_path: "device.external_ip", ocsf_field: "src_endpoint.ip" }
- { source_path: "device.local_ip", ocsf_field: "device.ip" }
- { source_path: "device.os_version", ocsf_field: "src_endpoint.os.name" }
- { source_path: "device.platform_name", ocsf_field: "src_endpoint.os.type" }
- { source_path: "device.mac_address", ocsf_field: "src_endpoint.mac" }
- { source_path: "device.device_id", ocsf_field: "device.uid" }
- { source_path: "device.agent_version", ocsf_field: "metadata.product.version" }
- { source_path: "device.cid", ocsf_field: "cloud.account.uid" }
# ── Finding / analytic ────────────────────────────────────────────
- { source_path: "composite_id", ocsf_field: "finding_info.uid" }
- { source_path: "name", ocsf_field: "finding_info.title" }
- { source_path: "description", ocsf_field: "finding_info.desc" }
- { source_path: "created_timestamp", ocsf_field: "finding_info.created_time" }
# `time` is the MTTD anchor: the ingestion engine reads THIS field and no other
# to stamp detected_at. Without it the incident is anchored at ingestion, so the
# delay between Falcon detecting and Riposte collecting — over a day on a slow
# poll — is measured as zero. finding_info.created_time below does NOT serve
# this: it is the finding's own record of the same instant, read by nothing.
- { source_path: "created_timestamp", ocsf_field: "time" }
- { source_path: "updated_timestamp", ocsf_field: "finding_info.modified_time" }
- { source_path: "scenario", ocsf_field: "finding_info.analytic.name" }
- { source_path: "pattern_id", ocsf_field: "finding_info.analytic.uid" }
- { source_path: "confidence", ocsf_field: "confidence" }
- { source_path: "status", ocsf_field: "status" }
# ── MITRE ATT&CK ──────────────────────────────────────────────────
- { source_path: "tactic", ocsf_field: "attacks.tactic.name" }
- { source_path: "tactic_id", ocsf_field: "attacks.tactic.uid" }
- { source_path: "technique", ocsf_field: "attacks.technique.name" }
- { source_path: "technique_id", ocsf_field: "attacks.technique.uid" }
# ── Triggering process — the actor ────────────────────────────────
- { source_path: "filename", ocsf_field: "actor.process.name" }
- { source_path: "cmdline", ocsf_field: "actor.process.cmd_line" }
- { source_path: "filepath", ocsf_field: "actor.process.file.path" }
- { source_path: "sha256", ocsf_field: "actor.process.file.hashes.sha256" }
- { source_path: "md5", ocsf_field: "actor.process.file.hashes.md5" }
- { source_path: "user_name", ocsf_field: "actor.user.name" }
- { source_path: "user_id", ocsf_field: "actor.user.uid" }
# ── Parent process ────────────────────────────────────────────────
- { source_path: "parent_details.cmdline", ocsf_field: "actor.process.parent_process.cmd_line" }
# ── Detected file — the subject ───────────────────────────────────
- { source_path: "filename", ocsf_field: "file.name" }
- { source_path: "filepath", ocsf_field: "file.path" }
- { source_path: "sha256", ocsf_field: "file.hashes.sha256" }
- { source_path: "md5", ocsf_field: "file.hashes.md5" }
- { source_path: "alleged_filetype", ocsf_field: "file.type" }
# ── IOC / observable ──────────────────────────────────────────────
- { source_path: "ioc_value", ocsf_field: "observables.value" }
- { source_path: "ioc_type", ocsf_field: "observables.type" }