Detection & Reporting
monsys’ Detection & Reporting module observes what happens on your hosts around authentication + source IP, and reports suspicious patterns with full context. The system does not auto-act — the sysadmin stays in control via existing Emergency Actions (TOTP-gated, Ed25519-signed).
This is a deliberate choice: auto-block features (CrowdStrike-style) are spoofable (attacker can cause legitimate IPs to be blocked) and don’t fit NIS2 separation-of-duties. monsys provides the evidence, the human decides.
In the dashboard
Section titled “In the dashboard”- Sidebar → Security → Detection (under OBSERVE)
- KPI tiles at top: open events / acknowledged / window
- Filter: time window (1h/24h/7d/30d) + status (open/acknowledged/all) + rule kind
- Click an event in the left list → context panel on the right loads:
- Host + src IP + country + RIR + target user + count + window
- MITRE ATT&CK TTPs (e.g. T1110.001 for SSH brute force)
- “Suggested next steps” — text guidance with explicit pointer to the manual Emergency Action for escalation
- “Related auth-events (same IP)” — what else did this IP try in the same time window
- “Similar findings this week (same IP)” — did this IP hit other hosts in your fleet?
- Click Acknowledge when investigated (event drops out of “open” view)
What we detect
Section titled “What we detect”| Rule kind | Default config | MITRE TTP |
|---|---|---|
auth_brute_force (per user) | >10 failures in 5min | T1110.001 |
auth_brute_force (per src_ip) | >20 failures in 5min | T1110.001 |
auth_invalid_user | >10 unique non-existent users from 1 IP in 10min | T1589.002 |
auth_new_country | successful login from country not seen for user in 30d | T1078 |
geo_blocked_country | any connection from operator-config country | T1078 |
usb_new_device | USB device not in the per-host baseline | T1200 |
The USB baseline is built automatically from a host’s first hardware inventory; any later, unknown device raises a detected event. As with all detections: observe + report, no auto-block.
Beyond detection rules, the agent’s hardware and user signals also feed the risk logic elsewhere in the hub: a weak or missing password policy counts toward Trust Score and compliance checks, and an insecure Wi-Fi network (open, WEP or TKIP) shows up as a recommendation with severity high or medium.
On first deploy, the 4 default rules are seeded per tenant. Modify or
add via /security/detection/rules (v2 — for now via API:
POST /api/v1/detection/rules).
What hosts must do (opt-in per agent)
Section titled “What hosts must do (opt-in per agent)”Detection requires the agent to read /var/log/auth.log (or
/var/log/secure on RHEL) and ship parsed events to the hub. This is
off by default because usernames + src IPs are PII.
Enable per host in /etc/monsys/agent.toml:
auth_event_shipping_enabled = trueRestart agent: sudo systemctl restart monsys-agent. Events ship
within 1 minute. Note: the monsys service user needs read access to
/var/log/auth.log; on Debian/Ubuntu membership of the adm group is
enough (sudo usermod -aG adm monsys). The shipper starts at the
current log position, historical lines are not backfilled. Privacy: everything stays in your tenant scope (RLS)
and aggregated signals only surface at the event level on the hub
(no raw log lines stored).
GeoIP — not MaxMind, RIR
Section titled “GeoIP — not MaxMind, RIR”For country mapping, monsys uses RIR delegated stats files (RIPE/ARIN/APNIC/AFRINIC/LACNIC). These are public, daily-refreshed lists directly from the allocating registry. No MaxMind licence, no attribution required, EU-pull-friendly, and more accurate at country level than commercial databases (it’s by definition the source of truth for IP allocation).
Limitation: country + ASN only, no city/lat-lng. For exact-coordinate impossible-travel a separate source would be needed (later).
The GeoIPWorker on the hub pulls the 5 RIR files every 24h (~25 MB
total), parses them into ranges, populates geoip_country_ranges.
Detection worker does one index seek per src_ip to look up country + RIR.
What monsys does NOT do
Section titled “What monsys does NOT do”- No automatic
iptablesblocks orusermod -L - No pre-issued EATs that self-fire on detection signals
- No network-level packet inspection (we read logs, not packets)
- No ML / sequence detection (start rule-based, ML only when baselines are stable for months)
- No integration with external SIEMs (we ARE the evidence source, not an agent-feeder to Splunk/Datadog)
Auto-resolve behaviour
Section titled “Auto-resolve behaviour”Detected events do not auto-close. The sysadmin explicitly acknowledges via the “Acknowledge” button — by design to keep audit trail (“on 2026-05-21 14:23 alice@acme.com dismissed event X as benign”). Events older than 30 days are purged by TimescaleDB’s chunk-retention policy (configurable in mig 097).
Or via API (advanced — for automation)
Section titled “Or via API (advanced — for automation)”# List open events last 24hcurl 'https://app.monsys.ai/api/v1/detection/events?since=24h&ack=open' \ -H "Authorization: Bearer $TOKEN"
# Detail with related + similar findingscurl https://app.monsys.ai/api/v1/detection/events/<id> \ -H "Authorization: Bearer $TOKEN"
# Acknowledge after investigationcurl -X POST https://app.monsys.ai/api/v1/detection/events/<id>/acknowledge \ -H "Authorization: Bearer $TOKEN"
# Add a geo-blocked country rulecurl -X POST https://app.monsys.ai/api/v1/detection/rules \ -H "Authorization: Bearer $TOKEN" \ -d '{ "name": "Block KP traffic", "rule_kind": "geo_blocked_country", "config": {"countries": ["KP"]}, "severity": "high", "enabled": true }'What does NOT belong on this page
Section titled “What does NOT belong on this page”- Manual Emergency Actions (IsolateNetwork etc.) → see Emergency console
- Audit trail of executed EATs → see Transparency log
- CVE-based detection (kernel + application deps + OS packages) → see Kernel CVE pipeline and OS-package CVE matching