Upsilon query syntax
Upsilon expresses queries as field comparisons joined by Boolean operators. The field’s namespace selects the source of the data.
Fields and namespaces
Section titled “Fields and namespaces”Use namespace.field:value for an exact comparison:
domain.permutation:example.comemail.sender_from_domain:example.comcanary.edge_outcome:unexpectedIn 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.
Boolean operators
Section titled “Boolean operators”Use uppercase AND, OR, and NOT. Precedence is parentheses, then NOT, then AND, then OR.
(domain.permutation:*login* OR domain.permutation:*account*) ANDdomain.classification.phishing:>0.8domain.classification.phishing:>0.8 ANDNOT 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.
Strings and keywords
Section titled “Strings and keywords”| 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.
Slash patterns and execution
Section titled “Slash patterns and execution”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 and booleans
Section titled “Numbers and booleans”Numbers support :>, :>=, :<, :<=, :=, and :!=.
domain.levenshtein_distance:<=3 ANDdomain.classification.phishing:>0.8Classification scores use 0–1 values. An attachment size uses bytes. Check the field description for its units.
canary.policy_mismatch:trueCompare date fields with an ISO date, a timestamp, or a supported relative expression such as now-7d.
email.observed_on:>=now-7ddomain.registration_metadata.registration_date:>=2026-01-01Use explicit age suffixes when comparing whole days:
domain.registration_metadata.registration_date.days_since:<=30domain.registration_metadata.expiration_date.days_until:<=90Email 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.
Arrays and lists
Section titled “Arrays and lists”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:@@cloudflareUse .len to inspect array length:
domain.dns_a.len:>=2The 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.
IP addresses and networks
Section titled “IP addresses and networks”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.10domain.dns_a:#192.0.2.0/24 OR domain.dns_aaaa:#2001:db8::/32Public web identifiers
Section titled “Public web identifiers”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.identifiersThe 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.
Nested enrichment selectors
Section titled “Nested enrichment selectors”Selectors expose values from nested enrichment structures:
domain.sitemap.title:*for\ sale* ORdomain.business_intel.company_names:Spaceship.comdomain.ports.port:[25 587 993] ANDdomain.ports.unique_port_count:>2Page-semantics selectors use the same independent matching model:
domain.page_semantics.site_purpose:financial_service ANDdomain.page_semantics.requests_account_password:trueSeparate 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.
Field references
Section titled “Field references”Prefix a right-hand field with $ to compare against its value:
email.sender_from_domain:$email.sender_mail_from_domainBoth 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.
Validation and missing data
Section titled “Validation and missing data”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.