Loading

Custom query rules

Custom query rules search your Elasticsearch indices using a KQL or Lucene query and generate an alert whenever one or more documents match.

Custom query rules are the right fit when:

  • You need to detect known indicators, field values, or simple boolean conditions, such as a specific process name, a registry path, or a combination of event fields.
  • The detection logic can be expressed as a single query without requiring event ordering, aggregation, or comparison against external threat feeds.
  • You want to reuse an existing Kibana saved query or Timeline query as the basis for a detection.

Custom query rules are not the best fit when you need to:

Custom query rules require at least one Elasticsearch index pattern or data view that contains the events you want to match. The indices must be accessible to the user who creates or last edits the rule, because the rule executes with that user's API key privileges.

The following examples use the detections API request format to show how custom query rules are defined. Each example is followed by a field-by-field breakdown.

This rule detects SSH logins by root or admin users, which may indicate unauthorized access or a policy violation.

{
  "type": "query",
  "language": "kuery",
  "name": "SSH login by privileged user",
  "description": "Detects SSH login events by root or admin users.",
  "query": "event.category: \"authentication\" and event.action: \"ssh_login\" and (user.name: \"root\" or user.name: \"admin\")",
  "index": ["filebeat-*", "logs-system.*"],
  "severity": "high",
  "risk_score": 73,
  "tags": ["SSH", "Authentication", "Privilege Escalation"],
  "interval": "5m",
  "from": "now-6m"
}
		
Field Value Purpose
type "query" Identifies this as a custom query rule.
language "kuery" Uses KQL syntax. The other accepted value is "lucene".
query event.category: "authentication" and ... Matches authentication events where the event.action is ssh_login and the user is root or admin. The and/or operators combine conditions in KQL.
index ["filebeat-*", "logs-system.*"] Searches Filebeat and Elastic Agent system integration indices. Must match the indices where SSH events are ingested.
severity / risk_score "high" / 73 Reflects the security impact. Root SSH logins are high-severity in most environments.
interval / from "5m" / "now-6m" Runs every 5 minutes and looks back 6 minutes, creating a 1-minute overlap so short ingestion delays don't cause missed events.

This rule detects PowerShell execution with Base64-encoded commands, a technique commonly used to obfuscate malicious scripts. The regular expression requires Lucene syntax because KQL does not support regex matching.

{
  "type": "query",
  "language": "lucene",
  "name": "Suspicious PowerShell encoded command",
  "description": "Detects PowerShell invocations that use the -EncodedCommand parameter.",
  "query": "process.name:powershell.exe AND process.args:/.*\\-(e|ec|en|enc|enco|encod|encode|encoded|encodedc|encodedco|encodedcom|encodedcomm|encodedcomma|encodedcomman|encodedcommand) .+/",
  "index": ["winlogbeat-*", "logs-endpoint.events.*"],
  "severity": "medium",
  "risk_score": 47,
  "interval": "5m",
  "from": "now-6m"
}
		
Field Value Purpose
language "lucene" Required for the /.../ regex syntax in the query. KQL does not support regular expressions.
query process.name:powershell.exe AND process.args:/.../ Uses a Lucene regex to match any truncation of the -EncodedCommand flag (PowerShell allows partial parameter names). The AND operator is uppercase in Lucene, unlike KQL's lowercase and.
index ["winlogbeat-*", "logs-endpoint.events.*"] Covers Windows event logs (Winlogbeat) and Elastic Defend endpoint events.

This rule detects failed login attempts and uses alert suppression to group repeated failures by user and host, reducing alert noise during brute-force attacks.

{
  "type": "query",
  "language": "kuery",
  "name": "Repeated failed login attempts",
  "description": "Detects failed authentication events grouped by user and host.",
  "query": "event.category: \"authentication\" and event.outcome: \"failure\"",
  "index": ["filebeat-*", "logs-system.*", "winlogbeat-*"],
  "severity": "medium",
  "risk_score": 47,
  "interval": "5m",
  "from": "now-6m",
  "alert_suppression": {
    "group_by": ["user.name", "host.name"],
    "duration": { "value": 5, "unit": "m" },
    "missing_fields_strategy": "suppress"
  }
}
		
Field Value Purpose
alert_suppression.group_by ["user.name", "host.name"] Groups matching events by user and host. All events with the same user.name and host.name within the suppression window produce a single alert instead of one per event. Accepts up to 3 fields.
alert_suppression.duration { "value": 5, "unit": "m" } Sets the suppression window to 5 minutes. Accepted units are s (seconds), m (minutes), and h (hours).
alert_suppression.missing_fields_strategy "suppress" When a suppression field is missing from a document, the event is still suppressed into a single alert. Use "doNotSuppress" to create individual alerts for documents missing the field.

The following settings are specific to custom query rules. For settings shared across all rule types (severity, risk score, schedule, actions, and so on), refer to Rule settings reference.

Index patterns or data view
The Elasticsearch indices or data view the rule queries when searching for events. Index patterns are prepopulated with the indices configured in the default Elastic Security indices advanced setting. Alternatively, select a data view from the drop-down to use its associated index patterns and runtime fields.
Custom query
The KQL or Lucene query that defines the main detection logic. Other fields such as filters or exceptions can be used to narrow the scope of the query.
Saved query (optional)
A Kibana saved query to use as the rule's detection logic. When loaded dynamically, the rule inherits changes to the saved query automatically. When loaded as a one-time copy, the query is embedded in the rule and can be edited independently.
Timeline query (optional)
Import a query from a saved Timeline to use as the rule's detection logic. The imported query populates the Custom query field.
Suppress alerts by (optional)
Reduce alert fatigue by consolidating multiple instances of the same event into a single alert. For details, refer to Alert suppression.
Required fields (optional)
An informational list of fields the rule needs to function. This does not affect rule execution. It helps other users understand the rule's data dependencies.
Related integrations (optional)
Associate the rule with one or more Elastic integrations to indicate data dependencies and allow users to verify each integration's installation status.