Skip to main content

Query languages

Huntbase lets you query in the language that fits the data you're after — a unified SQL dialect across every connected source, the native language of a single SIEM, a graph language for the entity graph, STIX patterns for indicator sweeps, or plain English that Scout translates for you. This page lists each language, how you pick one, and the parameter and time-range conventions that work everywhere.

The language pill menu in a query tab, showing natural language, connected sources and no connected source groups

Choose a language

In a query tab, the first pill in the query bar selects the language. The menu is grouped by what your connections can serve:

GroupContents
natural languageAuto — describe what you're looking for and Scout translates it.
connected sourcesLanguages that at least one connection in your current scope can run.
no connected sourceLanguages nothing in scope serves yet. Dimmed but still selectable, so you can draft a query before the matching connection exists.

Which group a language lands in depends on your connections. As a rule of thumb:

LanguageTypically served by
AutoAny source — Scout picks the language and connections for you.
SQLiteEvery connected product, through Huntbase's unified schema.
osqueryEndpoint Control (osctrl) fleets and other osquery-based products.
CypherThe Huntbase entity graph — no connection needed.
KQL (Huntbase Lake)Your data lake stores plus Huntbase's own — no connection needed.
SPLSplunk connections.
KQLMicrosoft Sentinel and Azure Data Explorer connections.
ES|QL, ES Query DSLElastic connections.
STIXAny connection with a STIX translator (see below).

When you open a query template from the Library, the language is locked to the template's language.

Auto (natural language)

Type what you want in plain English and Scout turns it into a query, chooses the connections, and decides the time window. Use it when you don't know which table or index holds the answer.

show me failed logins for admin accounts from outside the US in the last day

Scout's translated query is shown before it runs so you can review it, edit it, or switch to the underlying language.

SQLite

Unified SQL across all connected data sources. Tables map to normalized datasets, so the same query runs against every product that supplies the data. Use the Schema option in the query bar's ⋯ menu to browse platforms, datasets and columns and insert names into the editor.

SELECT user_name, src_ip, COUNT(*) AS attempts
FROM authentication
WHERE status = 'Failure'
AND time > datetime('now', '-{{days_back:number}} days')
GROUP BY user_name, src_ip
HAVING attempts > 10
ORDER BY attempts DESC;

osquery

SQLite over your endpoint fleet: each endpoint exposes its state as tables (processes, users, listening_ports, and so on). With osquery selected, a fleet pill in the query bar lets you target the whole fleet, filter by tag, OS or hostname, or pick exact endpoints. See Endpoint Control.

SELECT p.pid, p.name, p.path, p.cmdline, u.username
FROM processes p
JOIN users u ON p.uid = u.uid
WHERE p.path LIKE '/tmp/%'
OR p.path LIKE '/dev/shm/%';

Cypher

Graph query language for the Huntbase entity graph — users, hosts, IPs, files, processes, and the relationships between them. Cypher runs against Entity graph rather than a connection.

MATCH (u:user)-[:AUTHENTICATED_TO]->(h:device)<-[:AUTHENTICATED_TO]-(other:user)
WHERE u.name = {{user}}
RETURN h.hostname, collect(other.name) AS also_logged_in
LIMIT 50

KQL (Huntbase Lake)

Kusto over the Huntbase data lake. Like Cypher it needs no connection — the query bar shows Data lake instead of a connection picker, because one query searches Huntbase's own store plus every data lake store provisioned for your organization at once. See Data lake.

The pill says KQL (Huntbase Lake) to distinguish it from KQL, which is the Microsoft Sentinel passthrough further down this page. The syntax is the same Kusto you already know; the target is different.

telemetry
| where command_line has "-enc"
| where store == "northwind-eu"
| take 100

Results carry a store column naming which store each row came from, and the results panel reports how many stores were searched — and warns you if any were skipped, because that makes your answer incomplete. The time-range pill applies.

What the dialect supports

Lake KQL is a documented subset of Kusto: filtering, projection, aggregation and take over a single table.

Not supportedInstead
joinQuery each table separately.
letInline the expression.
mv-expand

One difference to watch: has matches a substring here, not a whole token.

An unsupported query fails fast with a clear error rather than being quietly reinterpreted, so pasting a complex Sentinel query and getting a refusal is the expected outcome — not a bug.

SPL

Splunk Processing Language, passed straight through to a Splunk connection. Huntbase adds the time-range pill's window as the search's earliest/latest bounds.

index=main sourcetype=WinEventLog:Security EventCode=4625
| stats count BY Account_Name, src_ip
| where count > 10
| sort - count

KQL

Kusto Query Language for Microsoft Sentinel and Azure Data Explorer connections, passed through natively. The time-range pill bounds the query.

SigninLogs
| where ResultType != 0
| summarize attempts = count() by UserPrincipalName, IPAddress
| where attempts > 10
| order by attempts desc

ES|QL

Elasticsearch's piped query language, passed through to an Elastic connection. The time-range pill bounds the query.

FROM logs-*
| WHERE event.category == "authentication" AND event.outcome == "failure"
| STATS attempts = COUNT(*) BY user.name, source.ip
| WHERE attempts > 10
| SORT attempts DESC
| LIMIT 100

ES Query DSL

Elasticsearch Query DSL in Lucene query-string form, passed through to an Elastic connection. The time-range pill is applied as a range filter.

event.category:authentication AND event.outcome:failure AND NOT source.geo.country_iso_code:US

STIX

STIX 2.1 pattern expressions for indicator-based sweeps. A STIX pattern is written once and translated per connection into that connection's native language, so a single run can check the same indicator across every source that supports it.

[ipv4-addr:value = '203.0.113.50'] OR [domain-name:value = 'malicious.example.com']

Match a file by hash:

[file:hashes.'SHA-256' = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855']
note

STIX patterns carry their own time qualifiers (START / STOP), and each connection's translator applies its own default lookback. The time-range pill is hidden for STIX so the two don't conflict.

Parameters

Any language can contain parameters. Write {{name}} in the query and Huntbase renders a field for it in the parameter strip under the query bar; the value is substituted when you run. Templates saved to the Library keep their parameters, so anyone running them fills in the same fields.

Syntax

{{name}}                 string (default)
{{name:type}} typed parameter
{{name:enum[a,b,c]}} pick from a fixed set
  • Names may contain letters, digits, underscores and hyphens, and must start with a letter or underscore.
  • The first occurrence of a name sets its type; reuse the same {{name}} anywhere in the query.
  • Every detected parameter is required. When you save a template, the Parameters editor lets you set a description and a Default value for each one.

Types

TypeField shownNotes
stringTextDefault when no type is given.
numberNumber
booleanToggle / select
datetimeText (date and time)
dateText (date)
listTextComma-separated values, sent as a list.
enum[…]SelectOptions come from the brackets, e.g. {{sev:enum[low,medium,high]}}.
jsonTextRaw JSON passed through.
secretTextTreated as sensitive.

Time range

For SPL, KQL, ES|QL and ES Query DSL the query bar shows a time-range pill (for example Last 1 hour). The window you pick is sent with the run and applied by the connection natively — you don't need to repeat it in the query. SQLite, osquery and Cypher express time in the query body, Auto lets Scout decide, and STIX uses its own qualifiers, so the pill is hidden for those.

Tips

  • Start in Auto when you're unsure where the data lives; switch to the translated language to refine.
  • Use the Schema tree to confirm dataset and column names before writing SQLite — it also filters to what the selected language can query.
  • Keep native queries (SPL, KQL, ES|QL) bounded with the time-range pill rather than a hard-coded window; templates then stay reusable.
  • Prefer parameters over literals for anything you'll change between runs (usernames, hosts, lookback), then Save as template.
  • Field names in SQLite follow the OCSF-based normalized schema — see OCSF.

Next steps

  • Query workspace — the query bar, editor, results and export
  • Query templates — save parameterized queries to the Library
  • OCSF — the normalized schema behind SQLite queries
  • Connections — add the sources that unlock each language