StairQL Reference
Every StairQL prefix, the values each one accepts, and the rules for combining terms. The page to open when you are halfway through a query.
This page lists every StairQL prefix, the values each one accepts, and the rules for combining terms. It is a lookup page. If you are learning the language, read StairQL first and come back here for the field you cannot remember.
StairQL is in beta. The syntax is still evolving, so a prefix or an accepted value can change between releases. If a field you need is missing, tell us at [email protected].
Every prefix, alphabetically
Most prefixes have a short form and a spelled-out long form, and the two are interchangeable. "List" means the prefix accepts the [a,b,c] any-of form.
| Prefix | Long form | Matches | List |
|---|---|---|---|
a: | asset: | Asset name or ID, detected from the operand | yes |
ac: | assetcontains: | Asset name contains | no |
an: | assetname: | Asset name | yes |
ar: | assetregex: | Asset name matches a regular expression | no |
asset: | Asset name or ID, detected from the operand | yes | |
at: | assettag: | Asset tag, exact | no |
bucket: | prob: | Likelihood band, range only | no |
company: | companyname: | PE company name contains | no |
envfs: | envfirstseen: | First seen in your environment | no |
export: | exportfunction: | PE export function, exact | yes |
fc: | filecontains: | Filename contains | no |
few: | fileendswith: | Filename ends with | no |
filedesc: | filedescription: | PE file description contains | no |
fr: | fileregex: | Filename matches a regular expression | no |
fs: | firstseen: | First seen anywhere Stairwell can see | no |
fsw: | filestartswith: | Filename starts with | no |
hash: | MD5, SHA1, or SHA256 | yes | |
host: | hostname: | Hostname contains | no |
impdll: | importdll: | PE imported DLL, exact | yes |
impfunc: | importfunction: | PE imported function, exact | yes |
imphash: | Import hash, exact | yes | |
intname: | internalname: | PE internal name contains | no |
ip: | ipaddress: | IP address, exact | yes |
magic: | magicnumber: | File type, exact | yes |
mallabel: | Verdict label, exact | yes | |
md5: | A hash. Searches all three hash fields | yes | |
mime: | mimetype: | MIME type contains | yes |
oac: | objectassetcount: | How many of your assets hold the file | no |
objenv: | oe: | The file's environment, by ID or name | IDs only |
ogac: | objectglobalassetcount: | How many assets hold the file globally | no |
opinion: | Your team's recorded verdict, exact | yes | |
origname: | originalfilename: | PE original filename contains | no |
ot: | objecttag: | Object tag, exact | yes |
p | The automated verdict. p, p:true, p:false, !p | no | |
pc: | pathcontains: | Path contains | no |
pdb: | pdbfilename: | PE PDB filename contains | no |
pdbr: | pdbregex: | PE PDB filename matches a regular expression | no |
pew: | pathendswith: | Path ends with | no |
pr: | pathregex: | Path matches a regular expression | no |
product: | productname: | PE product name contains | no |
psw: | pathstartswith: | Path starts with | no |
rich: | richheaderhash: | PE rich header hash, exact | yes |
rt: | ruletag: | Rule tag, exact | no |
sha1: | A hash. Searches all three hash fields | yes | |
sha256: | A hash. Searches all three hash fields | yes | |
signed: | Signature verification result, exact | yes | |
size: | File size in bytes | no | |
tr: | threatreport: | Threat report, one at a time | no |
version: | productversion: | PE product version, exact or range | yes |
wk | wellknown | Well-known files | no |
yara: | YARA rule name, exact | yes | |
yr: | yararegex: | YARA rule name matches a regular expression | no |
Hashes
A bare hex string of 32, 40, or 64 characters is recognized as a hash without any prefix, and is matched across all three indexed hash fields.
0123456789abcdef0123456789abcdef # MD5
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa # SHA1
aaaa...64 chars total...aaaa # SHA256
The prefixed forms hash:, sha256:, sha1:, and md5: behave identically to the bare form and to each other. Each one searches all three hash fields, so the prefix you pick is a readability choice rather than a filter. All four accept a list.
hash:[aaa,bbb,ccc] # any of these three, any algorithm
sha256:[abc,def,123]
hash:[a,b,c] fs:5d+ # any of these, first seen in the last 5 days
Import hash is a separate field.
imphash:deadbeef
imphash:[deadbeef,cafebabe,face1234]
File size
size: takes a whole number of bytes. A trailing + means at least, a trailing - means at most. Units such as KB are not accepted.
| Form | Meaning |
|---|---|
size:1000 | Exactly 1000 bytes |
size:1000+ | 1000 bytes or larger |
size:1000- | 1000 bytes or smaller |
Time
fs: (long form firstseen:) matches the time the file was first seen anywhere Stairwell can see. All dates are read as UTC. For the time a file first appeared in your own environment, use envfs:.
| Operand | Meaning |
|---|---|
fs:today | First seen today, 00:00 to 24:00 UTC |
fs:today+ | At or after today 00:00 |
fs:today- | At or before today 00:00 |
fs:yesterday | First seen yesterday |
fs:2024-01-01 | First seen on exactly that day |
fs:2024-01-01+ | On or after that day |
fs:2024-01-01- | On or before that day |
fs:7d+ | Within the last 7 days |
fs:5d- | More than 5 days ago |
fs:2w+ | Within the last 2 weeks |
fs:24h+ | Within the last 24 hours |
fs:30m+ | Within the last 30 minutes |
The relative units are m for minutes, h for hours, d for days, and w for weeks. There is no month or year unit; use an absolute date for those.
Two terms give you a window, because terms are combined with AND:
fs:7d+ fs:5d- # between 5 and 7 days ago
Filename and path
| Prefix | Long form | Match style |
|---|---|---|
fc: | filecontains: | Filename contains, substring, case-insensitive |
pc: | pathcontains: | Path contains |
fr: | fileregex: | Filename matches a regular expression |
pr: | pathregex: | Path matches a regular expression |
fsw: | filestartswith: | Filename starts with, anchored as ^str |
few: | fileendswith: | Filename ends with, anchored as str$ |
psw: | pathstartswith: | Path starts with |
pew: | pathendswith: | Path ends with |
fc:malware # contains "malware"
fc:"evil file" # quote multi-word substrings
pc:Windows # path contains "Windows"
pc:`C:\Windows\System32` # backticks pass backslashes through unchanged
fr:evil.*\.exe # regular expression
pr:`C:\Program Files\.*` # regular expression over a Windows path
fsw:svc # filename starts with "svc"
few:\.exe # filename ends with a literal ".exe"
Two things to know:
- The contains prefixes are literal. Regular expression metacharacters in the operand are matched as themselves. Use
fr:orpr:when you want pattern semantics. - A bare dot in
few:andpew:is a wildcard, because those prefixes anchor a regular expression.few:.exematches.exe,aexe, andXexe. Escape it to match a literal dot:few:\.exe.
Assets
asset: (short form a:) is the umbrella prefix. If the operand has the shape of an asset ID and decodes as one, it matches the ID; anything else matches the asset name.
asset:desktop-01 # name or ID, detected from the operand
asset:"Windows Server" # multi-word, quoted, so it matches a name
asset:[host1,host2,host3] # any of these
a:desktop-01 # short alias
List elements have to be all names or all IDs. A mixed list is an error.
| Prefix | Long form | Match style |
|---|---|---|
an: | assetname: | Asset name, list supported |
ac: | assetcontains: | Asset name contains |
ar: | assetregex: | Asset name matches a regular expression |
an:desktop-01 # asset name, forced, even for an ID-shaped string
an:"Windows Server"
an:[s1,s2,s3]
ac:malware # asset name contains "malware"
ar:^wks-[0-9]+$ # asset name matches this pattern
Asset name lookups are substring matches, including the ones that look exact. an:host1 also matches host10 and myhost1. For a true exact match, anchor a pattern instead: ar:^host1$.
For "how many assets is this file on", see Object metadata.
Environments
objenv: (short form oe:) matches the environment the file was seen in. An operand shaped like an environment ID matches the ID; anything else matches the environment name. Name matching is case-insensitive.
objenv:Production # by name
objenv:"Prod West" # multi-word name, quoted
oe:Production # short alias
The list form takes IDs only. Environment names have no any-of form, so use OR for several names.
objenv:[ID1,ID2,ID3] # any of these environments
objenv:Production OR objenv:Staging # names, joined with OR
You do not need an ID to write a query. Match your own environments by name, which is the name you see in the environment picker, and read the ID off the Environments page in Stairwell when you want to pin a saved query to one for good.
Stairwell's own shared environments are the exception, because their IDs are the same for every customer:
| 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 |
| 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 |
Environment IDs are matched case-insensitively, so type them in whatever case you have them.
YARA rules
| Prefix | Long form | Match style |
|---|---|---|
yara: | Rule name, exact, list supported | |
yr: | yararegex: | Rule name matches a regular expression |
yara:Emotet
yara:"APT29 Dropper" # multi-word
yara:[Emotet,Trickbot,Qakbot] # any of these rules
yr:Cobalt.*
yr:^Pro_ # anchored
yararegex:^(APT|FIN)_[0-9]+$
A rule name match tells you the file matched that rule. That is evidence to look at, not a verdict on the file. See What is a YARA rule?.
PE metadata
For Portable Executable binaries. Substring matching is the default for human-readable strings. Function names, DLL names, version, and the rich header hash are exact.
| Prefix | Long form | Field | Match style |
|---|---|---|---|
pdb: | pdbfilename: | PDB filename | substring |
pdbr: | pdbregex: | PDB filename | regular expression |
company: | companyname: | Company name | substring |
product: | productname: | Product name | substring |
filedesc: | filedescription: | File description | substring |
intname: | internalname: | Internal name | substring |
origname: | originalfilename: | Original filename | substring |
version: | productversion: | Product version | exact, range, list |
export: | exportfunction: | Export function | exact, list |
impdll: | importdll: | Imported DLL | exact, list |
impfunc: | importfunction: | Imported function | exact, list |
rich: | richheaderhash: | Rich header hash | exact, list |
pdb:src/main.pdb # PDB path contains src/main.pdb
pdbr:`.*\.pdb$`
company:Microsoft # company name contains "Microsoft"
product:"Acme Office"
filedesc:installer
version:1.0.0 # exact version
version:1.0.0+ # 1.0.0 or later, semantic-version aware
version:2.5- # 2.5 or earlier
version:[1.0.0,2.0.0,3.0.0] # any of these
export:DllRegisterServer
impdll:kernel32.dll
impdll:[kernel32.dll,ntdll.dll]
impfunc:CreateFileA
rich:deadbeef
Object metadata
| Prefix | Long form | Meaning | Match style |
|---|---|---|---|
magic: | magicnumber: | File type, read from the file's own content | exact, list |
mime: | mimetype: | MIME type | substring |
opinion: | Your team's recorded verdict | exact, list | |
signed: | Signature verification result | exact, list | |
oac: | objectassetcount: | Asset count for this file, in your environments | range, exact |
ogac: | objectglobalassetcount: | Asset count for this file, globally | range, exact |
magic:EXE # any Portable Executable
magic:[EXE,ELF,MACHO] # any of these file types
mime:application/pdf # MIME type contains "application/pdf"
mimetype:zip # any MIME type containing "zip"
opinion:MALICIOUS
opinion:[MALICIOUS,GRAYWARE]
signed:VALID
signed:[INVALID,UNSUPPORTED]
oac:5+ # on 5 or more of your assets
oac:100- # on 100 or fewer of your assets
oac:5 # on exactly 5 of your assets
ogac:100+ # on 100 or more assets globally
ogac:42 # on exactly 42 assets globally
oac: and ogac: describe the file, not the asset: they count how many assets a given file touches. See Prevalence.
magic values
Values are case-insensitive.
| Family | Values |
|---|---|
| Executables | EXE ELF MACHO WASM |
| Archives and containers | ZIP TAR RAR GZ BZ2 XZ SEVENZ Z LZ AR CAB DEB RPM ISO EPUB CRX |
| Documents | PDF RTF PS DOC DOCX XLS XLSX PPT PPTX |
| Images | PNG JPEG JPEG2000 GIF WEBP BMP TIFF ICO HEIF PSD CR2 JXR DWG |
| Audio | MP3 M4A OGG FLAC WAV AAC AMR MIDI |
| Video | MP4 M4V MKV MOV AVI WMV MPEG WEBM FLV THREEGP |
| Fonts | WOFF WOFF2 TTF OTF EOT |
| Other | SQLITE SWF DCM NES |
Two of those are spelled out because a value cannot start with a digit: SEVENZ is 7z, and THREEGP is 3gp.
magic:EXE covers every Portable Executable variant, including .exe binaries, .dll libraries, .sys drivers, .ocx, .cpl, and .scr. To narrow to one of them, add a filename condition: magic:EXE few:\.dll for DLLs, magic:EXE few:\.sys for drivers.
opinion values
An opinion is your team's own recorded verdict on a file. See Setting Opinions.
| Value | Meaning |
|---|---|
MALICIOUS | Malicious |
GRAYWARE | Unwanted, but not malicious |
VULNERABLE | Has known vulnerabilities, not necessarily malicious |
BENIGN | Nothing bad found |
TRUSTED | Trusted across all environments |
NO_OPINION | No opinion recorded |
Values are case-insensitive.
signed values
The result of verifying the file's signature.
| Value | Meaning |
|---|---|
VALID | Signature verified |
INVALID | Signature did not verify |
UNSUPPORTED | Signature could not be verified, so the result is unknown |
Network
| Prefix | Long form | Match style |
|---|---|---|
ip: | ipaddress: | Exact, list supported |
host: | hostname: | Substring |
ip:1.2.3.4
ip:[1.2.3.4,5.6.7.8,9.10.11.12]
host:evil.com # hostname contains "evil.com"
hostname:c2.attacker
Both prefixes search the indicators found inside files and the ones observed during detonation. See Network Intelligence.
Threat reports
tr: (long form threatreport:) takes one report identifier. There is no list form, so use OR for several reports.
tr:APT123
threatreport:Lazarus2022
tr:APT123 OR tr:APT124
Well-known files
Well-known files are the ones Stairwell already recognizes, and excluding them is how most hunts cut the noise.
| Form | Meaning |
|---|---|
wk | Well-known files only |
wk:true | Same as wk |
!wk | Exclude well-known files |
wk:false | Same as !wk |
wellknown | Long form of wk |
Maliciousness
p: is the automated verdict.
| Form | Meaning |
|---|---|
p | Same as p:true |
p:true | The automated verdict is malicious |
!p | Same as p:false |
p:false | The automated verdict is not malicious |
p:true reflects the automated verdict only. It does not pick up the opinions your team has set. Ask for both when you want both:
p:true OR opinion:MALICIOUS
Verdict label
mallabel: matches the label attached to the verdict, such as a family name. Exact, list supported.
mallabel:Emotet
mallabel:[Emotet,Trickbot,Qakbot]
Likelihood band
bucket: (alias prob:) is range-only. The band is a comparison rather than an exact value, so the operand always needs a + for at least or a - for at most.
bucket:HIGH+ # HIGH or VERY_HIGH
bucket:MEDIUM- # MEDIUM, LOW, or unranked
prob:VERY_HIGH+
Bands, highest first: VERY_HIGH, HIGH, MEDIUM, LOW. Case does not matter.
The longer PROBABILITY_ prefixed form is also accepted, so bucket:PROBABILITY_HIGH+ means the same thing as bucket:HIGH+. Use the short form; the prefixed one exists because it is what the CEL equivalent and the product's own saved queries use.
bucket:HIGH with no suffix, and bucket:[A,B] as a list, are both rejected.
Tags
| Prefix | Long form | Field | List |
|---|---|---|---|
ot: | objecttag: | Object tag | yes |
at: | assettag: | Asset tag | no |
rt: | ruletag: | Rule tag | no |
ot:campaign-foo
at:critical
rt:apt
Tag matching is exact. Asset tags and rule tags take a single value, so use OR for several.
Tag matching is case-sensitive today. If you applied the tag as Critical, then at:critical does not match it. Use the case you applied. This is a known beta rough edge.
Per-environment first-seen
envfs: (long form envfirstseen:) matches the time the file first appeared in your environment, as opposed to fs:, which is the first time it was seen anywhere Stairwell can see. It takes the same date and range operands as fs:.
envfs:today # first seen in your environment today
envfs:7d+ # in the last 7 days
envfirstseen:2024-01-01+ # on or after Jan 1 2024
Use fs: for "has this ever existed" and envfs: for "when did this reach us".
Combining terms
Implicit AND
Space-separated terms are combined with AND.
p:true fs:today asset:DESKTOP-123
Explicit AND
p:true AND fs:today
The keyword is case-insensitive, so AND, And, and and all work. There is no && symbol form; use the word.
Same-field OR, with a list
[a,b,c] means any of these values.
asset:[A1,B2,C3] # asset is A1, B2, or C3
hash:[a,b,c]
imphash:[x,y]
yara:[R1,R2]
objenv:[e1,e2] # environment IDs
an:[s1,s2,s3]
The list form is exact-match only. The contains, regular expression, starts-with, and ends-with prefixes (fc:, fr:, pc:, pr:, fsw:, few:, psw:, pew:, yr:, ac:, ar:, pdbr:) reject a list. Use OR for those, and for tr:, at:, and rt:.
Cross-field OR
Use the OR keyword for alternatives across different fields, and for any prefix that rejects a list. Both OR and || are accepted, and the keyword is case-insensitive.
tr:APT1 OR yara:APT1_Loader # in that report, or matching that rule
hash:abc123 OR an:host1
fc:`.sys` OR fc:`.exe` # same field, contains prefix
(yara:APT1 AND fs:today) OR p:true # nested
p:true || fc:`.exe` # symbol form
Same environment, same asset, same import
When you AND together terms that all describe one environment, one asset, or one import pair, StairQL requires the same one to satisfy all of them.
objenv:Prod AND (envfs:today OR envfs:yesterday)
That reads as "one of your environments is Prod and saw the file today or yesterday", not "Prod somewhere, and some environment saw it today". You can usually write what you mean without thinking about it. Stacking many OR groups over the same family can be rejected with an error, in which case split the query.
Precedence and grouping
AND binds tighter than OR, the same precedence CEL and SQL use. Without parentheses, alternatives are read as OR over AND-groups.
a OR b AND c # parsed as a OR (b AND c)
a AND b OR c AND d # parsed as (a AND b) OR (c AND d)
Parentheses force the other grouping, and nest freely.
(a OR b) AND c
((a OR b) AND c) OR d
Parentheses only mean grouping at a boundary between terms. Inside a value they are part of the value, so fc:"(foo)" and pr:`(a|b)` pass them through as written. Operators inside a quoted value are never split: fc:"foo OR bar" is one substring match.
Negation
! negates a term.
!fc:safe # filename does not contain "safe"
!wk # not well-known
!an:A1 # asset name is not A1
!an:[A1,B2,C3] # asset name is none of those
!size:1000+ # not 1000 bytes or larger, so smaller than 1000
Negation works on contains, equality, lists, and ranges. It does not work on the regular expression prefixes; see What is not supported yet.
Quoting and escaping
When in doubt, use backticks. `...` is a raw literal: every character between the backticks is taken as typed, backslashes included.
| Quote | Backslash handling | When to use |
|---|---|---|
`...` | None. Every character is a literal | Recommended. Windows paths, regular expressions, anything with a backslash |
"..." | \\ becomes \, \" becomes ", other escapes pass through | When the value contains a double quote |
'...' | Same as "..." | Alternative when the value contains a double quote |
pc:`C:\Windows\System32` # path contains that literal string
fr:`evil\.exe` # pattern with an escaped dot
psw:`\\server\share` # UNC path prefix
fc:`.sys` # filename contains a literal ".sys"
For the regular expression prefixes (fr:, pr:, fsw:, few:, psw:, pew:, yr:, yararegex:, pdbr:), all three quote styles are treated as raw, so backslashes reach the pattern unchanged.
Quotes work inside lists, and styles can be mixed.
an:[`A1`,`B2`,`C3`]
an:[`A1`,"B2",'C3',D4]
Case sensitivity
StairQL normalizes operands to match how each field is stored, so most of the time you type the value the way it looks in the app.
- Case-insensitive: hashes, asset names, environment names and IDs, filename and path substrings, hostnames, verdict labels,
magicvalues, MIME types, opinions, signature results. - Case-sensitive: tags, on objects, assets, and rules. Use the case you applied.
- Passed through unchanged: numbers, sizes, and timestamps.
What is not supported yet
- Environment-scoped rule queries. "Any rule in environment X", without naming a rule or a rule tag, has no StairQL form. CEL expresses it with
rule.environment_id. - Negated regular expressions.
!fr:,!pr:,!fsw:,!few:,!psw:,!pew:, and!yr:are not accepted. Negation on contains, equality, lists, and ranges works. p:truecovering opinions.p:trueis the automated verdict only. Writep:true OR opinion:MALICIOUSfor both.- Case-insensitive tag matching. See Tags.
- Last-seen time. StairQL filters on first-seen. There is no per-file last-seen-anywhere timestamp to filter on.
If one of these blocks your team, tell us at [email protected]. Knowing which gap costs you the most is what decides the order they close in.
What should I read next?
- StairQL, the guide that teaches the language rather than listing it.
- CEL Query Language, the explicit form, and the fields StairQL has no prefix for.
- Example Queries, for working queries to adapt.
Updated 4 days ago