Skip to content

Upsilon query syntax

Upsilon expresses queries as field comparisons joined by Boolean operators. The field’s namespace selects the source of the data.

Use namespace.field:value for an exact comparison:

domain.permutation:example.com
email.sender_from_domain:example.com
canary.edge_outcome:unexpected

In alert rules, unqualified fields retain the Domain fallback. For example, permutation:example.com and domain.permutation:example.com select the same Domain field. The compatibility-only created_on field must remain unqualified and records lookup-result creation time. Some source-specific search surfaces supply their own target; use the syntax documented for that surface.

See signals and namespaces for the catalogs and rules across namespaces for execution constraints.

Use uppercase AND, OR, and NOT. Precedence is parentheses, then NOT, then AND, then OR.

(domain.permutation:*login* OR domain.permutation:*account*) AND
domain.classification.phishing:>0.8
domain.classification.phishing:>0.8 AND
NOT domain.geolocation.country:[US CA GB]

Conditions over one namespace apply to one record. Across namespaces, a top-level AND requires every source to have a match; OR requires at least one. Cross-source matching does not correlate individual records.

A nested group that mixes namespaces and changes from AND to OR (or vice versa) is rejected. Same-connective nesting is flattened. Negation across namespaces and cross-namespace field references are also rejected.

Intent Syntax
Exact value domain.permutation:example.com
Not equal domain.kind:!=typosquatting
Contains domain.permutation:*login*
Starts with domain.permutation:login*
Ends with domain.permutation:*.com
Exists _exists_:domain.http_banner
Missing NOT _exists_:domain.http_banner

Quoted values preserve spaces for exact matching and list membership:

domain.sitemap.title:"Example account"
domain.technologies:["Google Analytics" "Google Tag Manager" Nginx]

Escape spaces in unquoted wildcard or array-containment values:

domain.http_banner:*nginx\ 1.18*

A keyword field is an exact label, such as canary.edge_outcome. Use exact values, lists, and existence checks rather than free-text patterns.

email.sender_from_domain:/^example[.]com$/

Slash-delimited patterns are regular expressions, including in Domain rules. Use *text* for an explicit substring condition.

Domain matching and database-backed queries use different regular-expression engines. Prefer portable patterns and validate against the intended execution surface; a preview does not guarantee identical behavior for every regex construct.

Numbers support :>, :>=, :<, :<=, :=, and :!=.

domain.levenshtein_distance:<=3 AND
domain.classification.phishing:>0.8

Classification scores use 0–1 values. An attachment size uses bytes. Check the field description for its units.

canary.policy_mismatch:true

Compare date fields with an ISO date, a timestamp, or a supported relative expression such as now-7d.

email.observed_on:>=now-7d
domain.registration_metadata.registration_date:>=2026-01-01

Use explicit age suffixes when comparing whole days:

domain.registration_metadata.registration_date.days_since:<=30
domain.registration_metadata.expiration_date.days_until:<=90

Email and Canary date predicates share the rule’s evaluation time. Domain date predicates use the time at which each result is matched, so conditions at a time boundary can differ from a preview. Age comparisons count elapsed whole days. The Email and Canary lookback setting still bounds which events can be read.

A list matches any of the listed values. For an array field, any element can match a listed value.

domain.geolocation.country:[US CA GB]
email.recipient_domains:[example.com example.org]

Use @ for array containment and @@ when every element must contain the value:

domain.dns_ns:@*cloudflare*
domain.dns_ns:@@cloudflare

Use .len to inspect array length:

domain.dns_a.len:>=2

The parser also has .min and .max for compatible array fields. It has no .avg suffix. Operator support depends on the field type and execution target; successful parsing alone is not execution validation.

Use the # prefix with Internet Protocol (IP) fields for an address or a Classless Inter-Domain Routing (CIDR) range.

domain.dns_a:#192.0.2.10
domain.dns_a:#192.0.2.0/24 OR domain.dns_aaaa:#2001:db8::/32

domain.identifiers matches one exact, case-sensitive kind=value pair:

domain.identifiers:"google_tag_manager=GTM-ABC123"
NOT domain.identifiers:"meta_pixel=123456789012345"
_exists_:domain.identifiers

The first = separates kind and value. Both must occur in the same identifier object. Identifier fields do not support wildcards, partial matching, ranges, lists, or the field:* existence shorthand. Use _exists_: instead.

Selectors expose values from nested enrichment structures:

domain.sitemap.title:*for\ sale* OR
domain.business_intel.company_names:Spaceship.com
domain.ports.port:[25 587 993] AND
domain.ports.unique_port_count:>2

Page-semantics selectors use the same independent matching model:

domain.page_semantics.site_purpose:financial_service AND
domain.page_semantics.requests_account_password:true

Separate selectors can match different nested entries within one Domain result. A rule over a page title and an external link does not necessarily mean the link appeared on that same page. Likewise, the two page-semantics conditions above can match different captured pages. A missing requests_* Boolean is unknown, not false.

Prefix a right-hand field with $ to compare against its value:

email.sender_from_domain:$email.sender_mail_from_domain

Both fields must be in the same namespace and have compatible types. Event execution rejects unsupported multi-valued right-hand fields, including selectors that can produce multiple values.

A valid query must use known public fields, compatible operators, and a supported Boolean shape for its target. A field that is in the catalog can still be absent from an individual record.

Use an existence check when presence matters. Do not infer execution support from syntax validation alone, or treat independent source previews as evidence of a complete cross-namespace match.