1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# yaml-language-server: $schema=https://timescale.github.io/rsigma/rsigma.schema.json
#
# rsigma configuration file.
#
# Precedence (low to high):
# compiled defaults < /etc/rsigma < ~/.config/rsigma < .rsigmarc < ./rsigma.yaml < env < CLI flags
#
# Discovery: place this at ./rsigma.yaml, ~/.config/rsigma/config.yaml, or
# /etc/rsigma/config.yaml, or point at it with `--config <path>`.
# Regenerate the JSON Schema with: rsigma config schema
version: 1
global:
# Diagnostic log format on stderr: text | json (maps to --log-format).
log_format: text
# Color policy for human-friendly output: auto | always | never.
# `auto` honors NO_COLOR and disables color when stdout is not a TTY.
# color: auto
# Default structured output format: json | ndjson | table | csv | tsv.
# Default behavior (when unset): pretty JSON on a TTY, NDJSON when piped.
# output_format: json
daemon:
# Path to a Sigma rule file or directory.
rules: /etc/rsigma/rules
# Builtin pipeline names (ecs_windows, sysmon) or YAML file paths.
pipelines:
# External dynamic-source files or directories (repeatable).
sources:
# Post-evaluation enricher config file.
# enrichers: /etc/rsigma/enrichers.yml
api:
# Bind address for health, metrics, and the HTTP/OTLP API.
addr: "0.0.0.0:9090"
# TLS settings (ignored unless built with the daemon-tls feature).
# tls:
# cert: /etc/rsigma/tls/cert.pem
# key: /etc/rsigma/tls/key.pem
# client_ca: /etc/rsigma/tls/ca.pem
# min_version: "1.3"
# allow_plaintext: false
input:
# Event source: stdin | http | nats://host:port/subject
source: stdin
# Log format: auto | json | syslog | plain | logfmt | cef
format: auto
# Default timezone offset for RFC 3164 syslog.
syslog_tz: "+00:00"
# Strip a leading UTF-8 BOM from RFC 5424 syslog messages (RFC 5424 treats
# it as an encoding marker, not content). Set false to keep it byte-for-byte.
syslog_strip_bom: true
# Channel capacity for source->engine and engine->sink queues.
buffer_size: 10000
# Max events processed per engine lock acquisition.
batch_size: 1
# jq filter / JSONPath query to extract the event payload (mutually exclusive).
# jq: ".event"
# jsonpath: "$.event"
output:
# Detection sinks (repeatable): stdout | file://path | nats://host:port/subject
# | otlp(s)://host:port (gRPC) | otlphttp(s)://host:port (HTTP); the `s`
# variants use TLS. Optional query suffixes: ?on_full=drop (best-effort),
# ?compression=gzip (OTLP), and for TLS ?ca=, ?client_cert=, ?client_key=
# (PEM paths; the last two enable mutual TLS) and ?tls_domain= (SNI).
sinks:
# Dead-letter queue for events that fail processing.
# dlq: "file:///var/lib/rsigma/dlq.ndjson"
# Seconds to wait for in-flight events to drain on shutdown.
drain_timeout: 5
# Include the full event JSON in each detection.
include_event: false
# Pretty-print JSON output.
pretty: false
# Async delivery tuning, shared by every sink. The per-sink queue depth
# follows input.buffer_size; append ?on_full=drop to a sink URL for
# best-effort (lossy) delivery instead of backpressure.
# Max delivery retries per sink before a result is routed to the DLQ.
retry_max: 3
# Base and ceiling backoff (milliseconds) for delivery retries.
backoff_base_ms: 100
backoff_max_ms: 5000
# Max results per delivery batch, and max ms a partial batch waits.
batch_max: 64
batch_flush_ms: 50
# Webhook config files or directories (repeatable; maps to --webhook).
# Each declares template-driven HTTP sinks; see the webhooks guide.
# webhooks:
# - /etc/rsigma/webhooks/slack.yaml
correlation:
# Suppression window for correlation alerts (e.g. 5m, 1h, 30s).
# suppress: 5m
# Action after a correlation fires: alert | reset
action: alert
# Correlation event inclusion: none | full | refs
event_mode: none
# Max events stored per correlation window group.
max_events: 10
# Hard cap on correlation state entries across all correlations and
# group keys; stalest entries are evicted at the cap.
max_state_entries: 100000
# Cap on retained entries within a single group's window state.
# Unset = unbounded.
# max_group_entries: 10000
# Extra event field names for timestamp extraction.
# timestamp_fields: ["@timestamp"]
# Behavior when no timestamp field is found: wallclock | skip
timestamp_fallback: wallclock
# Suppress detection output for correlation-only rules.
no_detections: false
state:
# SQLite database for persisting correlation state across restarts.
# db: /var/lib/rsigma/state.db
# Seconds between periodic state snapshots.
save_interval: 30
engine:
# Enable bloom-filter pre-filtering of positive substring matchers.
bloom_prefilter: false
# Match-detail verbosity for detection output: off (default), summary, full.
# summary adds the matcher kind/selection (and keyword/absence matches);
# full also records the matched pattern. off keeps the {field, value} shape.
match_detail: off
# Memory budget (bytes) for the bloom index. No effect unless bloom_prefilter.
# bloom_max_bytes: 1048576
# Observe event field keys for coverage reporting.
observe_fields: false
# Hard ceiling on distinct field names tracked by the observer.
observe_fields_max_keys: 10000
# Allow include directives to reference remote (HTTP/NATS) sources.
allow_remote_include: false
# Enable the cross-rule Aho-Corasick pre-filter (daachorse-index feature).
# cross_rule_ac: false
# HTTP egress policy applied to dynamic-source and enrichment HTTP clients.
# default = block link-local + cloud-metadata (SSRF defense, allow loopback / private).
# strict = also block loopback + RFC1918 private (recommended for hardened deployments).
# permissive = allow every resolved address (only for tightly controlled environments).
egress_policy: default
# Live event tap (GET /api/v1/tap). Records a bounded window of the live
# event stream as a replayable NDJSON fixture. Opt-in: disabled by default
# because it can exfiltrate raw event traffic. Enable it (here or with
# --enable-tap) only behind mTLS. The tuning keys below are config-file-only.
tap:
# Accept tap sessions. Disabled by default; set true (or pass --enable-tap)
# to enable.
enabled: false
# Per-session bounded buffer; a full buffer drops events (counted)
# rather than ever applying backpressure to the engine.
buffer_events: 8192
# Maximum concurrent capture sessions (a session over the cap gets 409).
max_sessions: 2
# Largest accepted capture window (a longer ?duration gets 400).
max_duration: 5m
# Live detection tail (GET /api/v1/detections/stream). Streams detection
# results (not raw events) as NDJSON. Opt-in: disabled by default, enabled
# here or with --enable-tail. The tuning keys are config-file-only.
tail:
# Accept tail sessions. Disabled by default; set true (or pass
# --enable-tail) to enable.
enabled: false
# Per-session bounded buffer; a full buffer drops detections (counted)
# rather than ever applying backpressure to the sink task.
buffer_events: 8192
# Maximum concurrent tail sessions (a session over the cap gets 409).
max_sessions: 2
# NATS secrets (creds/token/password/nkey) are NOT configurable here by
# design; supply them via environment variables. Ignored unless daemon-nats.
# nats:
# consumer_group: rsigma
eval:
# Default rules path for `rsigma engine eval`.
# rules: ./rules
# pipelines: [sysmon]
input_format: auto
syslog_tz: "+00:00"
# Strip a leading UTF-8 BOM from RFC 5424 syslog messages. Set false to keep it.
syslog_strip_bom: true
fail_on_detection: false
backtest:
# Default rules path for `rsigma rule backtest`.
# rules: ./rules
# Event corpus file(s) or directory(ies), walked recursively.
# corpus: [./corpus]
# Expectations YAML (per-rule fire-count assertions).
# expectations: ./expectations.yml
# Policy for a rule that fires with no covering expectation: fail | warn | ignore.
# Unset here so the expectations-file default applies; the CLI flag overrides both.
# unexpected: warn
# pipelines: [sysmon]
# Input log format for non-NDJSON corpus files.
input_format: auto
syslog_tz: "+00:00"
# Strip a leading UTF-8 BOM from RFC 5424 syslog messages. Set false to keep it.
syslog_strip_bom: true
coverage:
# Default rule file(s) or directory(ies) to map onto ATT&CK (repeatable).
# rules: [./rules]
# Cross-reference against the Atomic Red Team index: a local index.yaml, an
# atomic-red-team `atomics/` directory, or a URL.
# atomics: https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/Indexes/index.yaml
# Baseline ATT&CK Navigator layer (local path or URL); e.g. the SigmaHQ heatmap.
# baseline: https://raw.githubusercontent.com/SigmaHQ/sigma/master/other/sigma_attack_nav_coverage.json
# Target technique list (one technique ID per line; `#` comments allowed).
# targets: ./threat-model-techniques.txt
# Exit non-zero when a requested cross-reference reports uncovered techniques.
# fail_on_gaps: false
scorecard:
# `rule scorecard` fuses the backtest and coverage JSON reports into per-rule
# keep/tune/retire verdicts. The two reports are required; supply them on the
# command line (--backtest/--coverage) or here.
# backtest: ./backtest.json
# coverage: ./coverage.json
# Prometheus exposition snapshot or /metrics URL for production fire volume.
# metrics: http://localhost:9090/metrics
# When metrics is a Prometheus query-API base, range window for last-fired.
# metrics_window: 7d
# Triage disposition feed for the live false-positive ratio and MTTD/MTTR.
# triage: ./triage.json
# Program-artifact output path (.md or .html).
# report: ./scorecard.md
# CI policy: fail (exit 1) on verdicts at or worse than none | tune | retire.
fail_on: none
# Verdict thresholds (SOC quality-metrics defaults).
min_precision: 0.8
tune_max_precision: 0.5
retire_max_precision: 0.1
# Minimum total volume for a keep verdict.
min_volume: 1
# Staleness window in days (enforced only when last-fired is known).
stale_window: 30
# Live false-positive-ratio ceiling.
max_fp_ratio: 0.5
visibility:
# Logsource/field to ATT&CK data-source mapping table (local path or URL).
# Unset uses the bundled default table; a bare `--mapping` flag uses the
# curated default URL.
# mapping: ./mapping.json
# Exit non-zero when a rule-expected data source has no observed telemetry
# (every mapped field sits in the broken-coverage `missing` set).
# fail_on_blind_spots: false
# `rsigma mcp serve` settings. The auth token is NOT configurable here by
# design; supply it via --auth-token or RSIGMA_MCP_AUTH_TOKEN.
mcp:
# Bind address for the Streamable HTTP transport (`--http`). Unset = stdio.
# http_addr: 127.0.0.1:9100
# Lint config file applied by the lint_rules tool (`--lint-config`).
# lint_config: .rsigma-lint.yml
# Default root for relative path-based tool calls (`--rules-dir`).
# rules_dir: ./rules