Mergen · Detection

Rule Reference

Mergen ships 54 built-in detection rules (40 PostgreSQL/system + 14 MongoDB) plus a declarative, admin-authored custom-rule engine. What each rule catches, its severity, and its license tier are below.

Critical · Warning · Info Tier: basic (always on) · advanced (advanced_analytics license)
How detection works

The agent captures the wire protocol (eBPF uprobes in-line, or AF_PACKET network capture / off-host collector), parses each statement into an AST (statement kind, tables read/written, columns, WHERE predicates, function calls), and evaluates every rule against that parsed stream — queries, bind parameters, result rows, and errors. For MongoDB, OP_MSG commands (compressed included) are parsed to verb + collection + filter shape.

Built-in rules

Injection

5
sql_injection crit basic Stacked queries (;-chained), UNION-based injection, and WHERE tautologies (1=1, 'a'='a').
jsonb_filter_bypass warn advanced JSONB @> containment against an empty container — an always-true filter bypass.
hibernate_native_query_marker info advanced ORM native-query comment markers — inventories raw SQL escaping the ORM (injection surface).
mongo_where_injection Mongo crit basic $where server-side JavaScript in filters (NoSQL injection).
mongo_js_execution Mongo crit basic eval / mapReduce server-side JavaScript execution.

Recon

4
system_catalog_recon crit advanced Reads of system catalogs; credential/role catalogs (pg_shadow, pg_authid) are Critical.
large_object_read warn basic Direct pg_largeobject reads — bypasses lo_* permission checks.
mongo_unfiltered_read Mongo warn basic find / count / distinct without a filter.
mongo_enumeration Mongo info basic listDatabases / listCollections enumeration.

Exfiltration

9
excessive_data_export warn advanced SELECT * with no effective row filter (CTE- and subquery-aware).
exfil_direct warn advanced COPY TO, pg_read_file, pg_read_binary_file, pg_ls_dir, lo_export, lo_get, lo_put.
exfil_byte_volume warn advanced Cumulative result-byte volume over a threshold in a window — slow-drain exfiltration.
exfil_time_pattern warn advanced Regular-interval repeated querying (beaconing / scheduled scraping).
dblink_usage warn advanced dblink() cross-database access — lateral movement and SSRF surface.
foreign_data_access crit advanced FDW surface: CREATE SERVER / USER MAPPING, foreign tables, file_fdw file reads.
mongo_unfiltered_delete Mongo crit basic delete with an empty filter — collection-wide destruction.
mongo_unfiltered_update Mongo crit basic update with an empty filter — collection-wide modification.
mongo_excessive_data_export Mongo warn basic Collection-wide read/export patterns.

Compliance / PII

5
pii_content warn basic PII (SSN, card, e-mail…) in query literals, bind parameters, or result rows.
turkish_pii crit basic KVKK Turkish PII: TCKN, IBAN, GSM, plate — with validity checks (TCKN checksum).
ozel_nitelikli_veri_access crit basic KVKK special-category (health, religion, biometric…) data access.
sensitive_column_read warn basic Reads touching operator-tagged sensitive columns (configurable list).
mongo_pii_in_response Mongo warn basic PII patterns in response documents.

Privilege

9
role_privilege_escalation crit advanced CREATE/ALTER ROLE SUPERUSER / CREATEROLE / BYPASSRLS (crit); REPLICATION (warn).
role_impersonation warn advanced SET SESSION AUTHORIZATION / SET ROLE to a high-privilege role.
priv_esc_chain crit advanced Multi-step privilege-escalation chains correlated within a session window.
dangerous_grant crit basic GRANT of pg_execute_server_program / pg_read_all_data… (crit); GRANT TO PUBLIC (warn).
ddl_by_non_admin crit basic DDL executed by a user outside the configured admin allowlist.
security_definer_function warn advanced CREATE FUNCTION … SECURITY DEFINER — persistent privilege-escalation surface.
dangerous_extension crit advanced CREATE EXTENSION untrusted-language (plpython3u, plperlu…).
mongo_auth_bypass Mongo crit basic Comparison-operator injection on sensitive fields ({password:{$ne:""}}).
mongo_privileged_op Mongo crit basic createUser / dropUser / role grants / createRole …

DoS

6
resource_abuse warn basic Backend-stalling / row-byte-exploding primitives: pg_sleep, generate_series bombs.
cartesian_product warn basic Unfiltered multi-table cartesian products.
unbounded_recursive_cte warn basic WITH RECURSIVE without a top-level LIMIT.
redos warn basic Catastrophic-backtracking regex operands (nested quantifiers).
lock_abuse warn basic Explicit LOCK TABLE … IN ACCESS EXCLUSIVE MODE.
failed_login_burst crit basic N auth failures within a sliding window (default 5 in 60s).

DDL / Persistence

7
dangerous_ddl crit basic COPY FROM/TO PROGRAM (RCE), untrusted-language CREATE FUNCTION, risky DDL.
trigger_backdoor warn advanced CREATE EVENT TRIGGER — DDL-fired persistence.
audit_tamper crit advanced ALTER SYSTEM on logging/replication; archive_command / *_preload_libraries (crit).
mongo_destructive_command Mongo crit basic drop, dropDatabase, dropIndexes, renameCollection, dropAll*.
mongo_admin_command Mongo warn basic replSet* / shard / fsync / compact cluster administration.
mongo_profiling_change Mongo warn basic Profile-level changes (audit-trail tampering).
mongo_session_kill Mongo warn basic killSessions / killOp — session/operation termination.

Anomaly

5
off_hours_query info basic Activity outside the configured business-hours window.
bulk_delete crit basic DELETE without WHERE (full-table wipe); tables can be allowlisted.
large_result_set info basic A single query returning an unusually large number of rows.
ueba_anomaly crit advanced Per-entity behavioral baseline: EWMA + robust z-score over rate/tables/bytes/off-hours/write-ratio/new-table.
ueba_peer_anomaly crit advanced Peer-group outlier vs application cohort (median + MAD robust statistics).

Audit

4
login_audit info basic Per-login audit records: login_success (Info) / login_failed (Warning) with user/db/IP.
query_error info basic Failed statements with SQLSTATE + message (permission-denied etc. are Warning).
clock_anchor_skew warn basic Advisory when agent clock skew vs DB / console exceeds 5 minutes (audit-time integrity).
framer_desync_burst warn advanced Bursts of wire-protocol desync — capture-integrity / evasion signal.

Custom rules

Beyond the built-ins, admins author declarative custom rules in the console (Rules → Custom rules). They are pushed to agents over the heartbeat channel (version-gated, no restart) and evaluated on the same parsed streams as built-in rules. No code execution: matching is purely declarative, and regexes use a linear-time (RE2-class) engine — a custom rule cannot ReDoS the agent.

{
  "id": "crown_jewel_read",
  "severity": "critical",         // info | warning | critical
  "db_engine": "pg",              // pg | mongo
  "enabled": true,
  "match": {
    "statement_kinds": ["Select"],
    "tables_regex": "^payroll_",
    "columns_regex": "salary|iban",
    "command_regex": "",          // raw-SQL escape hatch
    "user_in": [],
    "user_not_in": ["app_readonly"],
    "require_no_where": false
  },
  "message_template": "payroll read: {kind} on {tables} by {user}",
  "rate": { "count": 10, "window_secs": 60, "group_by": "user" }
}

Fields

id Stable rule identifier; appears as rule_id on detections; disable per host/group/global like any built-in.
severity info | warning | critical (aliases warn / crit; anything else falls back to info).
db_engine pg (parsed SQL stream) or mongo (parsed MongoDB command stream).
enabled A false definition is never compiled.
match The match conditions (AND semantics). An empty object matches everything.
message_template Detection message; placeholders below.
rate If present: a count-in-window threshold.

Match conditions (AND — every present condition must hold)

An empty match matches every statement — always constrain at least one axis.

statement_kinds Parsed statement kind (Select, Insert, Update, Delete, Copy, CreateRole, AlterRole, Grant). Empty = any.
tables_regex Any table the statement reads or writes.
columns_regex Any column the statement reads.
command_regex The raw SQL text — the escape hatch when AST fields are not enough.
user_in / user_not_in Session user allow / deny (exact match).
require_no_where Fires only when the statement has NO WHERE predicates (full-table shape).
time_window Scopes the rule to a UTC time window: {start, end (HH:MM), negate, days}. start>end wraps overnight; negate matches OUTSIDE the window; days Mon=0..Sun=6. Absent = any time.
MongoDB (db_engine: "mongo")

command_regex → command verb, tables_regex → collection, require_no_where → no filter document. Other match fields do not apply.

Message template placeholders

{kind} · {tables} · {columns} · {user}

Rate

With rate, the rule fires only when it matches ≥ count times within window_secs (sliding window). group_by:"user" keeps a per-user window; otherwise it is global.

Safety

An invalid regex skips that whole rule (logged) — never a crash or half-match. Severity aliases warn/crit; unknown → info. Scope (enable/disable per host/group/global) and alerting work exactly like built-in rules.