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?
| Entity | What it is |
|---|---|
object | Files Stairwell holds |
mal_eval | The verdict on a file |
pe | Portable Executable metadata for a file |
net | Hostnames and IP addresses found in files |
asset | Machines in your fleet |
rule | YARA rules |
tag | Tags applied by your team |
threat_report | Threat 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
| Field | Notes |
|---|---|
sha256, sha1, md5 | A specific hash |
hash | Matches any of the three |
hash_or_c2 | Matches any hash, or a hostname, or an IP address. Useful when you do not know what kind of indicator you were handed |
name | Filename |
path | File path |
size | Bytes as a number, or a string such as "1MB" |
magic | File type |
mime_type | MIME type |
imphash | Import hash |
pe_sections_sha256 | Hash of one or more PE sections |
authenticode_verification_result | VALID, INVALID, or UNSUPPORTED |
opinion | Your team's recorded call. See Setting Opinions |
opinion_update_time | When that call was last changed |
global_first_seen_time | First seen anywhere Stairwell can see |
first_seen_time | First seen in the environment |
environment_id, environment_name | Which environment |
origin | Currently web, for files submitted through the browser |
tag | A tag on the file |
mal_eval
| Field | Notes |
|---|---|
malicious | true or false |
label | A verdict label, such as a family name |
probability_bucket | The 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?
| Operator | Meaning | Example |
|---|---|---|
== | Equal | object.sha256 == "HASH" |
!= | Not equal | rule.status != ACTIVE |
<, <=, >, >= | Ordered comparison | rule.version > 5 |
in | One of a list | object.sha256 in ["h1","h2"] |
&& | And | a && b |
|| | Or | a || b |
! | Not | !mal_eval.malicious |
.contains() | Substring | mal_eval.label.contains("trojan") |
.matches() | Regular expression | rule.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 == trueHow 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.
| Query | View 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
| Feed | Environment ID |
|---|---|
| VirusShare | 6HP5R3-ZM7DAN-RB4732-X6QPCJ36 |
| Malshare | D7W6M6-BA9BS4-BQ23Z4-NKCNWQ96 |
| Malware Bazaar | D4447Q-WJJL6P-W7ME89-WHXJK8TW |
| Jotti | VR9Z98-4KU7ZC-PCNFEG-FURQ66FW |
| vxintel | TV6WCV-7Y79LE-BK79EY-C8GUEY46 |
| Threat Report Feeds | MKYSAR-3XN9MB-3VAK3R-888ZJUTJ |
| Stairwell Public Verdicts | TT9GM5-JUMD8H-9828FL-GAW5NNXE |
Rule feeds
| Feed | Environment ID |
|---|---|
| Stairwell OSINT | EB3DXY-3ZYFVH-6HNKJQ-GAPKHESS |
| Stairwell Methodology | GEG6FU-MRARGF-TLTM6X-H6MGDT5E |
| Stairwell Research | NQNJM6-5LSCAF-3MC5FJ-W8EKGW6N |
| Florian's Open Rules | NCS2SM-YHB2KT-SAFUDX-JC7F6WYA |
| Pro Rules | XAKLND-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.
Updated 19 days ago