Real scan of a disposable Elastic lab with deliberately missing, stale, late, and unused telemetry. Reproduce it with make record-scan-lab.
Why deadair
A rule can be enabled, scheduled, and error-free while the data it needs is gone. deadair reads the
live rule inventory, resolves each rule's inputs using the backend's native semantics, and checks the
concrete sources behind them.
It catches:
rules whose index, alias, or data-stream selectors resolve to nothing;
rules whose matching sources are all stale or empty;
rules running with missing fields or an ingest-lag blind window;
healthy telemetry that no enabled detection reads.
deadair currently works with Elastic Security and OpenSearch Security Analytics.
Quick start
Download a binary for macOS, Linux, or Windows from
GitHub Releases, or install with Go:
go install github.com/alephnull-sh/deadair/cmd/deadair@latest
Connect a read-only SIEM credential:
deadair setup elastic # print the least-privilege setup
deadair check # verify the credential can scan
deadair scan # assess live rules and telemetry
Exit codes are stable: 0 is healthy, 1 means findings, and 2 means the scan failed.
How it works
Stage
What deadair does
Inventory
reads enabled detections and the inputs they declare
Resolve
asks Elastic or OpenSearch to resolve index patterns, aliases, data streams, selectors, and remote inputs
Measure
checks document count, freshest event, storage, field mappings, schema history, and ingest lag
Report
emits terminal, JSON, HTML, fleet rollups, and Prometheus metrics with the evidence behind each verdict
deadair proves whether a detection's observable telemetry prerequisites are present and healthy. It
does not prove that the rule logic is correct or that a simulated attack will produce an alert. Pair
it with static rule validation and end-to-end detection testing for those layers.
Findings
Finding
Meaning
First check
no matching source
none of the rule's inputs resolve to a visible index or data stream
pattern changes, missing integrations, and credential scope
all sources stale or empty
every resolved source is unusable right now
source cadence and the ingest path
missing fields
declared fields are absent from every matched source mapping
parser, package, and mapping changes
lag blind window
measured ingest lag exceeds the rule's lookback margin
rule interval, lookback, timestamp override, and pipeline delay
source degradation
a source is stale, empty, low-volume, or schema-drifted
source history and expected maintenance
unused telemetry
data is being stored but no enabled local detection resolves to it
disabled rules and intentional collection
Every verdict is limited to what the configured credential can see. JSON reports include the
configured expressions, resolved sources, resolution method, assessment status, backend metadata,
and capability evidence. See the usage guide for worked examples and triage.
Use the documented least-privilege roles for
Elastic or OpenSearch. The trusted
integration suite also proves that write attempts made with those credentials are rejected.
CI, fleets, and monitoring
# Gate a candidate rule against live source availability.
deadair scan --rule new-rule.json
# Fail only on new regressions between reports.
deadair diff yesterday.json today.json
# Scan multiple SIEM instances from one process.
deadair scan --fleet fleet.json
# Export cached scan results as Prometheus metrics.
deadair serve --interval 5m
scan --rule isolates the candidate rule from unrelated backlog. diff works with deterministically
redacted reports. Fleet configuration references secrets through environment variables rather than
storing secret values.
A candidate-rule gate and report diff against a throwaway Elastic stack.
Bug reports, sanitized fixtures, correctness cases, docs, and backend proposals are welcome. Start
with CONTRIBUTING.md and use the backend RFC template for adapter work.