InfraGuard

Detection Rulesets

A read-only catalog that normalizes every detection rule InfraGuard observes into 44 rulesets across 11 categories, showing live firing counts and, on click, the recent events each ruleset matched.

Overview — what it does

Detection Rulesets (/security/rulesets) is the canonical library that normalizes every detection rule InfraGuard observes and judges into 44 rulesets across 11 categories. The screen does three things in one place:

  1. Overview — lays out ruleset cards inside category sections and shows, for the selected time window (1h/6h/24h), the actual event count and last-seen timestamp each ruleset matched.
  2. Explanation — narrates each ruleset in three steps (what it detects · why it fires · worst case).
  3. Replay — clicking a card opens a modal with the recent events actually matched by that ruleset, in an engine-specific table.

The key design is the separation of classification structure from explanatory text. The structure (categories, ruleset keys, per-engine match rules) lives in the locale-independent static SOT App\Support\SecurityRulebook (cache-safe), while the explanatory text (name, meaning, evidence, risk) lives in resources/lang/{ko,en}/secrules.php. The frontend merges the two by key+category to render.

This screen is strictly read-only. It does not enable, disable, edit, or delete rulesets. It is a reference catalog that answers "what is being observed in this org right now, and what does it mean?" The place that actually changes detection constants (thresholds/windows) is Rules & Thresholds (Admin ▸ Rules).

The 44 rulesets are wired to real telemetry

Rulesets are not abstract rules — each is bound to a real collection table by a match rule (match). Every source is on the legacy_glory connection (the legacy DB the collector fleet fills).

Engine Match rule Source table Rulesets
Suricata IDS sig: lowercase substring match against an array of signature fragments suricata_alert_ct 33
Web (nginx) classifyWeb: priority, disjoint classification of is_suspicious requests by url/ua/status nginx_meta_ct 8
Kitsune ML source=kitsune: autoencoder anomaly IPs kitsune_detail_log 1
Heuristic (srct) source=srct: scan/rate heuristic runs srct_process_log 1
JA3 fingerprint source=ja3: JA3 variety (rotation) per source IP suricata_tls_ct 1

When to use

Layout

Top KPIs

KPI Label Meaning
total Rulesets Total rulesets in the catalog (always 44)
active Observed rulesets Rulesets that fired at least one event in the window (firing)
events Events in window Sum of event counts across all rulesets
cats Categories Category count (11)

Internally it also computes per-engine sums (kitsune and suricata event totals) so the numbers stay consistent with the "rulesets" stage of the Security defense funnel.

Controls

Category sections + ruleset cards

The 11 categories form sections in display order, and within each section rulesets are laid out in a minmax(600) card grid. Each card shows the ruleset name, an MDI icon, a severity badge (crit/warn/info), the in-window event count, the last-seen timestamp, and [Open]. With no events it shows "quiet / none observed in window".

# Category key Label Engine Rulesets
1 tcp_stream TCP stream integrity Suricata 10
2 packet_decode Packet decoding Suricata 4
3 protocol_anomaly Protocol anomaly Suricata 5
4 http_anomaly HTTP compliance Suricata 5
5 tls_anomaly TLS anomaly Suricata 5
6 dns_anomaly DNS anomaly Suricata 1
7 mail_anomaly Mail (SMTP) anomaly Suricata 3
8 web_attack Web attack patterns nginx 8
9 ml_anomaly ML anomaly detection Kitsune 1
10 heuristic_scan Heuristic scan srct 1
11 tls_fingerprint JA3 fingerprint JA3 1

How to use

1) Pick a window → read the landscape

First choose the window of interest (1h/6h/24h). Use active (observed rulesets) and each card's event count to see what is firing now. Note that the severity badge is an implied severity — most Suricata engine events are sev3 (informational), but the implication differs (noise / scan / exploit). The ruleset badge reflects this implication tone, not the raw sev.

2) Click a card → recent events modal

Clicking a card calls /security/rulesets/events?key=<rulesetKey>&range=<window> and opens a modal containing:

Engine-specific event table columns:

Engine Columns
Suricata time · src · dst · port · proto · signature · sev
nginx time · src · host · method · URL (rawurldecode, 180 chars) · status
Kitsune time · IP · anomaly score · sessions · blocked
srct time · scanned · blocked · note
JA3 time · IP · JA3 variety · TLS conns · SNI variety

3) Web attack classification priority (disjoint)

The 8 web (nginx) rulesets are mutually disjoint. A single is_suspicious=1 request is scanned in catalog definition order and attributed to exactly one first-matching ruleset; if it matches none, it falls to the catchall (web_suspicious_other). So the same request is never double-counted across two web rulesets.

Priority Ruleset key Match cue (url/ua) Severity
1 web_secret_scan .env .git wp-config id_rsa .aws credentials backup.sql .bak warn
2 web_path_traversal ../ ..%2f %2e%2e etc/passwd boot.ini proc/self crit
3 web_sqli union select information_schema sleep( or 1=1 %27or crit
4 web_xss <script onerror= javascript: document.cookie warn
5 web_rce_probe /bin/sh exec( system( jndi: ${ phpunit crit
6 web_admin_brute wp-login xmlrpc.php phpmyadmin /admin/login warn
7 web_bad_bot UA: sqlmap nikto masscan nuclei python-requests curl/ warn
8 web_suspicious_other (catchall — suspicious requests matching none of the above) info

For performance, web classification aggregates over the most-recent sample of 6,000 rows (repository cap 8,000). During heavy scans, events outside the sample may not be reflected — read the numbers as distribution/trend, not absolute counts.

4) What Suricata substring matching implies

Suricata rulesets fire on a lowercase substring match of the signature string. For example, stream_invalid_ts sums every event whose signature contains invalid timestamp. A single ruleset can bundle several actual signatures (visible as "matching signatures" chips in the modal), and the sig keywords of different rulesets are designed not to overlap.

5) Measured example (for reference)

An illustrative 24h snapshot: 37 of 44 rulesets firing, stream_invalid_ts 10,243, web_secret_scan 3,304 (mostly .env-family 404s), srct_heuristic 126,252, ja3_rotation 300 (variety 307/307). Values vary by org and time.

Data sources

All sources are the legacy_glory connection (read-only), reached only via config('database.connections.legacy_glory') — no hardcoded credentials.

Ruleset family Table Repository methods (excerpt)
Suricata (33) suricata_alert_ct signatureHistogram() · recentAlertsBySignatures() · distinctIpsBySignatures()
Web (8) nginx_meta_ct (is_suspicious=1) suspiciousRows($since, 6000)
Kitsune ML (1) kitsune_detail_log kitsuneCount() · kitsuneRecentInWindow()
Heuristic (1) srct_process_log srctBlockedSum() · srctRunsInWindow()
JA3 (1) suricata_tls_ct topJa3Ips($since, N, excludePrefixes)

Performance & caching

Access

Level convention: demo=1 · staff=5 · admin=10. Some areas are additionally gated by infr.level:N middleware. See RBAC Levels for the full grading scheme.

Troubleshooting & FAQ

All cards show "quiet"

Either there are no matching events in the selected window (default 24h), or the legacy_glory connection is unreachable. The service gracefully swallows source errors and shows empty counts (0) — cards do not disappear. Widen the window or check the connection.

Web ruleset counts differ from [Threats] / [Detections]

Web classification is a distribution aggregate over a most-recent sample of 6,000 rows (not an absolute count). It is also disjoint, so a request is attributed to exactly one ruleset. The authoritative event source follows each screen's own query.

A specific signature is not caught by any ruleset

Suricata matching is keyword substring matching. New/custom signatures the catalog does not cover are not summed into any ruleset count. To classify/explain them, add the signature keyword to SecurityRulebook's sig array — a code change, not a runtime setting.

JA3 offenders are 0 but there is heavy TLS traffic

The JA3 ruleset counts only source IPs with ja3_variety >= 2 (fingerprint rotation) as offenders. Without rotation, a source is treated as normal and not counted. Self-network IPs are also excluded.

An IP shows an internal badge in the event modal

That is a registered internal-network IP judged by SecurityScope::internalMatchers(). It prevents mistaking our own servers — which Suricata directionality can label as the "source" — for attackers, and hides the reputation button. The internal-network definition is managed under internal_networks in Operations Policy.

Related

The detection ruleset catalogue
The detection ruleset catalogue