nano SIEM
Search Commands

Search & Query Language

Search & Query Language

nano uses nPL (nano Pipe Language) — a powerful query language that makes searching and analyzing security logs intuitive and efficient. If you're familiar with piped query languages, you'll feel right at home with nPL.

Also available: Quick Reference — all 38 commands at a glance.

Understanding Fields

nano organizes log data into different field types, each optimized for specific search patterns. For detailed information, see Field Types & Search Performance.

Quick Overview:

  • Metadata Fields (timestamp, source_type, id) - Fastest, always present
  • Normalized Fields (src_ip, user, process_name) - Fast, heavily indexed
  • UDM Fields (525+ extended fields) - Good performance, comprehensive coverage
  • Enriched Fields (enriched_src_country, enriched_dest_asn) - Fast, pre-computed
  • Prevalence Fields (prevalence_min, prevalence_process_hash, etc.) - Ingest-time rarity scores (0-100)
  • Extension Fields (additional UDM fields) - Stored as dynamic JSON, searchable by name

Query Basics

Search for keywords across all fields:

failed login

This searches for events containing both "failed" and "login" in any field.

Field Filters

Search specific fields using field=value syntax:

user=admin
status=401
src_ip=192.168.1.100

Comparison Operators

OperatorDescriptionExample
=Equalstatus=200
!=Not equalstatus!=200
>Greater thanbytes>1000
<Less thanresponse_time<100
>=Greater or equalseverity>=5
<=Less or equalport<=1024

Logical Operators

Combine conditions with AND, OR, NOT:

# AND (implicit or explicit)
user=admin status=401
user=admin AND status=401

# OR
status=401 OR status=403

# NOT
user=admin NOT status=200

# Grouping with parentheses
(status=401 OR status=403) AND user=admin

Wildcards

Use * for wildcard matching:

# Wildcard in field value
user=admin*
filename=*.exe

# Wildcard keyword search
*malware*

Regex Matching

Use /pattern/ for regex searches:

# Regex on specific field
filename=/cmd\.exe$/

# Case-insensitive regex
user=/admin|root/i

# Complex patterns
CommandLine=/powershell.*-enc.*[A-Za-z0-9+\/=]{50,}/

Advanced Search Operators

IN Lists

Check if a field matches any value in a list:

status IN (200, 201, 204)
user IN ("admin", "root", "administrator")
EventID NOT IN (4624, 4625)

String Operators

OperatorDescriptionExample
LIKEPattern matching with % wildcardfilename LIKE "%.exe"
NOT LIKENegated pattern matchpath NOT LIKE "%temp%"
CONTAINSSubstring matchmessage CONTAINS "error"
STARTSWITHPrefix matchdomain STARTSWITH "evil"
ENDSWITHSuffix matchfilename ENDSWITH ".ps1"
# Examples
filename LIKE "%.dll"
CommandLine CONTAINS "powershell"
domain STARTSWITH "malicious"
path ENDSWITH "\\system32"

Function Filters

Use functions in search filters:

# Length check
len(password) < 8

# Lowercase comparison
lower(user) = "admin"

# Time-based filtering
timestamp > now() - INTERVAL 1 HOUR
age(timestamp) < 3600

Piped Commands

Transform and analyze results using piped commands with |. Results flow from left to right:

<search expression> | <command> | <command> | ...

Aggregation & Statistics

  • stats - Aggregate data with functions like count, sum, avg
  • chart - Create aggregated visualizations (alias for stats)
  • timechart - Time-based aggregations with automatic bucketing
  • streamstats - Calculate running statistics per event
  • eventstats - Add aggregate statistics to all events
  • bin - Bucket timestamps or numeric values

Filtering & Selection

  • where - Filter results based on conditions
  • head - Return first N results
  • tail - Return last N results
  • dedup - Remove duplicate events
  • top - Find most common values
  • rare - Find least common values
  • sample - Return random sample of events

Field Operations

  • eval - Create calculated fields
  • rename - Rename fields
  • fields - Include or exclude specific fields
  • table - Display specific fields
  • rex - Extract fields using regex
  • spath - Extract fields from JSON/XML
  • fillnull - Replace null values
  • mvexpand - Expand multi-value fields

Ordering & Formatting

  • sort - Order results by fields
  • reverse - Reverse order of events

Enrichment & Analysis

  • lookup - Enrich with lookup table data
  • inputlookup - Fetch data from external URLs for enrichment
  • prevalence - Filter or enrich based on artifact prevalence
  • resolve_identity - Resolve IP addresses to hostnames/users from EDR data
  • risk - Assign risk scores for risk-based alerting
  • anomaly - Detect statistical outliers
  • asset - Asset investigation view with identity resolution
  • cloud - Cloud investigation view with faceted summaries

Pattern Detection

  • transaction - Group related events
  • sequence - Detect ordered event patterns
  • funnel - Analyze conversion through sequential steps
  • tree - Visualize hierarchical relationships (process trees, web flows)

Subsearch Operations

  • append - Append subsearch results
  • join - Join with subsearch on common fields
  • format - Format subsearch results as string
  • return - Return field values from subsearch

Prevalence Filtering

nano provides two ways to filter by prevalence: ingest-time fields (recommended) and query-time enrichment.

Prevalence scores are computed at ingest time and stored directly in the logs. This is the fastest approach:

# Filter events with rare process hashes (score 0-25)
sourcetype = "sysmon" AND prevalence_process_hash <= 25

# Find events with any rare artifact
prevalence_min <= 10

# Combine with other filters
dest_ip != "" AND prevalence_dest_ip <= 15 | table timestamp, dest_ip, prevalence_dest_ip

Ingest-time prevalence fields:

FieldDescription
prevalence_file_hashScore (0-100) for file_hash. Lower = rarer.
prevalence_process_hashScore (0-100) for process_hash. Lower = rarer.
prevalence_dest_domainScore (0-100) for dest_host. Lower = rarer.
prevalence_dest_ipScore (0-100) for dest_ip (public IPs only).
prevalence_minMinimum of all scores (for filtering any rare artifact).

Score interpretation: 0-10 = Very rare, 11-25 = Rare, 26-50 = Uncommon, 51-100 = Common, 255 = N/A

Prevalence Slider

The search interface includes a Prevalence Filter slider next to the search button:

  • Drag left for rare artifacts only, right to show all
  • Quick presets: Very Rare (≤10), Rare (≤25), Uncommon (≤50), All
  • Automatically appends | where prevalence_min <= X to your query
  • Value is saved in URL for shareable links

Query-Time Prevalence Enrichment

For dynamic prevalence lookups (slower but always current), use the prevalence command:

# Filter rare hashes (seen on < 5 hosts)
* | prevalence hash_prevalence < 5 window=24h

# Filter rare domains
* | prevalence domain_prevalence < 3 window=7d

Time Ranges

Time Picker

Use the UI time picker to set the search time range:

  • Last 15 minutes
  • Last hour
  • Last 24 hours
  • Last 7 days
  • Last 30 days
  • Custom range

Time Filters in Query

Filter by time in your query:

# Relative time
timestamp > now() - INTERVAL 1 HOUR
timestamp > date_sub(now(), INTERVAL 24 HOURS)

# Absolute time
timestamp > "2025-01-01 00:00:00"
timestamp BETWEEN "2025-01-01" AND "2025-01-31"

# Age-based
age(timestamp) < 3600  # Less than 1 hour old

Query Examples

Security Use Cases

# Brute force detection
action=login status=failure
  | bin span=5m
  | stats count() as attempts by time_bucket, src_ip
  | where attempts > 10

# Rare process execution
EventID=1
  | prevalence hash_prevalence < 5 window=24h
  | table timestamp, Image, CommandLine, hash_prevalence

# Suspicious PowerShell
Image=*powershell.exe CommandLine=*-enc*
  | eval cmd_entropy = entropy(CommandLine)
  | where cmd_entropy > 4.5

# Privilege escalation
EventID IN (4672, 4673, 4674)
  | stats count() by user, PrivilegeList
  | where count > 5

# Data exfiltration
bytes > 10485760 dest_port IN (80, 443)
  | stats sum(bytes) as total_bytes by src_ip, dest_ip
  | where total_bytes > 104857600  # 100 MB

Log Analysis

# Error rate by service
level=error
  | bin span=5m
  | stats count() by time_bucket, service

# Slow requests
response_time > 1000
  | stats avg(response_time), max(response_time), count() by endpoint

# Top talkers
* | stats sum(bytes) as total_bytes by src_ip
  | sort -total_bytes
  | head 10

# Failed authentication sources
status IN (401, 403)
  | stats count() as failures by src_ip, user_agent
  | where failures > 5

Threat Hunting

# Beaconing detection
* | bin span=1m
  | stats count() as connections by time_bucket, src_ip, dest_ip
  | stats stdev(connections) as conn_stdev by src_ip, dest_ip
  | where conn_stdev < 0.5  # Consistent timing = beaconing

# Lateral movement
EventID=4624 LogonType=3
  | stats dc(dest_host) as unique_targets by src_ip
  | where unique_targets > 10

# Suspicious domains
* | eval domain = extract_domain(url)
  | eval domain_entropy = entropy(domain)
  | where domain_entropy > 4.0
  | prevalence domain_prevalence < 3

# Command and control
* | where is_public_ip(dest_ip)
  | stats sum(bytes) as total, count() as connections by dest_ip
  | where connections > 100 AND total < 10000  # Many small connections

Search Queuing

When the system is busy, your search may be queued rather than running immediately. This happens when the global or per-user concurrency limits are reached.

While queued, you'll see your position in the queue and an estimated wait time. You can cancel a queued search at any time using the cancel button.

The Active Searches panel (above the results area) shows all your current and recent searches — including queued, running, completed, and failed jobs. Click a completed search to reload its results.

Detection rules always run immediately and are never affected by search queuing.

For configuration details, see Search Concurrency.

Performance Tips

  1. Filter early — Apply time and field filters before piped commands
  2. Use specific fieldsuser=admin is faster than searching all fields
  3. Limit results — Use head to limit large result sets
  4. Avoid wildcards at start*admin is slower than admin*
  5. Use stats wisely — Group by low-cardinality fields when possible
  6. Time-based partitioning — Always specify a time range
  7. Aggregatestats is more efficient than returning raw events
  8. Sample for testing — Use sample when developing queries

Keyboard Shortcuts

  • Ctrl+Enter — Execute query
  • Ctrl+K — Open command palette
  • Ctrl+Space — Autocomplete
  • Ctrl+/ — Comment/uncomment
  • Ctrl+F — Find in results

Next Steps

On this page

On this page