CEL Query Language

CEL is the default filter language in Stairwell's search bar. The entities, every field they carry, the operators, and why a correct query returns nothing.

CEL is the filter language behind Stairwell's search boxes. You write a condition on an entity's fields and get back the subset that matches, whether you are narrowing files, assets, YARA rules, or network indicators. It is the default language in the search bar, and it is what the rest of the product generates when it hands you a query.

A condition has three parts:

entity.property OPERATOR value
object.md5 == "6f5902ac237024bdd0c176cb93063dc4"

The entity is what you are searching for, the property is one of its fields, and the value is what you are matching. That is the whole shape of the language; everything below is vocabulary.

Which entities can I query?

EntityWhat it is
objectFiles Stairwell holds
mal_evalThe verdict on a file
pePortable Executable metadata for a file
netHostnames and IP addresses found in files
assetMachines in your fleet
ruleYARA rules
tagTags applied by your team
threat_reportThreat reports

The entities you can combine in one query are the ones that describe the same result. object, mal_eval, pe, net, and asset all describe files and the machines holding them, so they mix freely. A rule condition describes rules, so it belongs in a query about rules.

Which fields does each entity have?

object

FieldNotes
sha256, sha1, md5A specific hash
hashMatches any of the three
hash_or_c2Matches any hash, or a hostname, or an IP address. Useful when you do not know what kind of indicator you were handed
nameFilename
pathFile path
sizeBytes as a number, or a string such as "1MB"
magicFile type
mime_typeMIME type
imphashImport hash
pe_sections_sha256Hash of one or more PE sections
authenticode_verification_resultVALID, INVALID, or UNSUPPORTED
opinionYour team's recorded call. See Setting Opinions
opinion_update_timeWhen that call was last changed
global_first_seen_timeFirst seen anywhere Stairwell can see
first_seen_timeFirst seen in the environment
environment_id, environment_nameWhich environment
originCurrently web, for files submitted through the browser
tagA tag on the file

mal_eval

FieldNotes
malicioustrue or false
labelA verdict label, such as a family name
probability_bucketThe likelihood band. See Verdicts

pe

export_function, import_dll, import_function, company_name, product_name, product_version, file_description, internal_name, original_filename, pdb_filename, rich_header_hash.

net

ip and hostname. See Network Intelligence.

asset

name, id, tag, count (how many of your assets hold the object), global_count (how widely the object is seen globally). See Assets and Prevalence.

rule

name, version, status (ACTIVE, INACTIVE, or ANCESTOR), environment_id, tag. See What is a YARA rule?.

tag and threat_report

tag.label, tag.value, and tag.identifier, which is the colon-joined form such as campaign:apt34. threat_report.id takes a report identifier.

Which operators are available?

OperatorMeaningExample
==Equalobject.sha256 == "HASH"
!=Not equalrule.status != ACTIVE
<, <=, >, >=Ordered comparisonrule.version > 5
inOne of a listobject.sha256 in ["h1","h2"]
&&Anda && b
||Ora || b
!Not!mal_eval.malicious
.contains()Substringmal_eval.label.contains("trojan")
.matches()Regular expressionrule.name.matches("[Aa]pt")

How do I match many values at once?

Use a list, which is how you sweep a report's worth of hashes in one query.

object.sha256 in ["hash1","hash2","hash3"]

And combine conditions with &&:

object.imphash == "abcd1234" && mal_eval.malicious == true

How do I filter by time?

Time fields take before() and after() against a timestamp:

object.global_first_seen_time.after(timestamp("2026-01-01T00:00:00Z"))

This is the one place where StairQL is markedly shorter, since it expresses the same window as fs:7d+. If most of your hunting is time-relative, use that language instead.

Why does my query return nothing?

Three reasons, in order of how often they are the reason.

The query names an entity the current view does not show. A query about rule returns nothing while you are looking at objects. Check the tab above your results.

QueryView to be on
object.sha256 == "hash"Objects
rule.name == "example"Rules

The value's case or exact form differs. Hash comparison is exact. Use .contains() or .matches() when you want anything looser than exact.

The condition is true of nothing. Loosen one clause at a time rather than rewriting the query, and you find out which clause was wrong.

One documented exception to be aware of: object.tag is handled by its own query path, and combining it with other conditions has historically not worked. If you need tags plus another filter, run the tag query and narrow from its results.

What are the environment IDs for Stairwell's shared feeds?

Scoping a query to a feed needs that feed's environment ID. These are Stairwell's
shared feed environments, so the IDs are the same for everyone.

Malware feeds

FeedEnvironment ID
VirusShare6HP5R3-ZM7DAN-RB4732-X6QPCJ36
MalshareD7W6M6-BA9BS4-BQ23Z4-NKCNWQ96
Malware BazaarD4447Q-WJJL6P-W7ME89-WHXJK8TW
JottiVR9Z98-4KU7ZC-PCNFEG-FURQ66FW
vxintelTV6WCV-7Y79LE-BK79EY-C8GUEY46
Threat Report FeedsMKYSAR-3XN9MB-3VAK3R-888ZJUTJ
Stairwell Public VerdictsTT9GM5-JUMD8H-9828FL-GAW5NNXE

Rule feeds

FeedEnvironment ID
Stairwell OSINTEB3DXY-3ZYFVH-6HNKJQ-GAPKHESS
Stairwell MethodologyGEG6FU-MRARGF-TLTM6X-H6MGDT5E
Stairwell ResearchNQNJM6-5LSCAF-3MC5FJ-W8EKGW6N
Florian's Open RulesNCS2SM-YHB2KT-SAFUDX-JC7F6WYA
Pro RulesXAKLND-DKWP3Z-56RL88-6XJ5NH46

Your own environments have their own IDs, which you can find in the environment
settings. See Environments.

What should I read next?

  • Example Queries, for working queries to adapt.
  • StairQL, the compact alternative, which is faster to type for interactive hunting.
  • Hunting and Search, for everything the search bar accepts besides a query.

Did this page help you?