Query Commands
Investigating by query
There is only so far the screens will take you. Checking the same condition across several hosts, or tying what you found to the result of another question, needs a query.
The commands this app adds let you leave a mark while investigating and collect those marks again afterwards, from inside a query. The flow is the same whether a person or an AI agent is driving it: ask questions, tag what you have judged, then gather the tags into a timeline.
Record keys
A tag belongs to one record. The name that identifies that record is its record key, written
tablename_yyyyMMdd_recordid:
The detail panel shows it, and search results carry it in the _record_key field.
Tagging — forensic-tag
Leaves a tag and a note on one record.
| Option | Required | What it is |
|---|---|---|
key | yes | The record key |
color | yes | 1 blacklist · 2 warning · 3 bookmark |
comment | no | Why you marked it |
Running it again on the same record with the same color does not add a second tag — it updates the note. Re-reading something and sharpening your judgement is not the same as flagging it twice.
The author is recorded as the account that ran the query, in the same place a tag left from the screen would be. It shows up in the Tags tab of the detail panel.
A record key belonging to another company comes back as not found.
Untagging — forensic-untag
| Option | Required | What it is |
|---|---|---|
key | yes | The record key |
color | no | One color, or every tag on the record if omitted |
It returns how many were removed in the removed field.
Collecting the tags — forensic-tags
Lists the records you marked.
| Option | Required | What it is |
|---|---|---|
type | yes | artifact, or a log schema code such as reg or winevent |
campaign-guids | no | Project GUIDs |
host-guids | no | Host GUIDs |
tables | no | Table names. Given, it overrides both filters above |
The output is record_key, color, comment, user_name, created_at and updated_at.
Because the note and the author come with it, you can read not only which records were marked but
why.
A record carrying several colors is reported with the most serious one, the same way the star in the grid works.
Matching indicators — match_forensic_*
Functions that compare a field against what you registered under Administration → Indicators.
| Function | Compared against |
|---|---|
match_forensic_md5(field) | MD5 |
match_forensic_sha1(field) | SHA1 |
match_forensic_domain(field) | Domains |
match_forensic_ip(field) | IP addresses |
The indicator list is read once, when the query is parsed. Anything registered while a query is running does not reach it, so rerun the query after adding indicators. What is compared against is the company of the account running the query.
match_forensic_ip takes an IP-typed value. If the column is text, wrap it in ip(...).
Listing images — forensic-images
Emits the company's evidence images as rows. The per-image tables carry only the image number in their names and nothing about which case they belong to, so recovering that number from the table name and joining it against this command is how you attach project and host names.
The output is id, guid, campaign_guid, campaign_name, host_guid, hostname, type,
file_name, zip_size, status, created_at and imported_at.
The other two
| Command | What it is for |
|---|---|
forensic-extract-indicators | Sits at the tail of a load query and harvests indicators from every value passing through. Imports append it themselves, so you will not write it |
forensic-add-host-partition | Records a partition found in evidence against its host. Called from an evidence type's load query |
collectors the import opened, so running it outside one fails.
Building a timeline from tags
Gathering the marks you left and re-reading the case through them is what these commands are for.
forensic-tags type=artifact campaign-guids="8c1d3e70-2b9a-4f6c-8e15-3d7a6b2c9f41"
| search color == 1
| sort created_at
| fields created_at, record_key, comment, user_name
That keeps the red tags and lays them out in the order they were made. The notes come with them, so what was judged a compromise — and why — reads in one pass.
To attach the original records' timestamps, join against their table on record_key. That is
what you do when you want the order things happened rather than the order you found them.