SIS CLI
Asset Graph & Asset-Path Queries
Every scanned file is modelled as a nested asset graph: the root document plus every artefact it
contains — archive entries, email parts, OOXML/OLE members, PDF embedded files and carved blobs, and
polyglot interpretations — as a single recursive tree. The engine always emits one (a bare root for a
flat document), so report.asset_graph is the source of truth for structure-aware querying.
You address nodes in that tree with an asset-path selector, an abbreviated-XPath grammar over the containment structure.
The asset-path grammar
An asset path is /-separated segments of <tag>:<name>, where <tag> is the container grammar tag
(zip, pdf, ole2, mht, iso, eml) and <name> is the member label. Wildcards and predicates
scope the match:
pdf:root— the root node.zip:root/zip:doc.pdf— a named entry.*— any single segment;**— any depth (recursive descent).[field=value]— a predicate on a node’s typed fields (see below).- A trailing
/<terminal>projects something about the matched nodes (findings, digest, text, …).
sis query bundle.zip "**" # every asset node
sis query bundle.zip "zip:root/*" # direct members of the root
sis query bundle.zip "**/[format=pe]" # any PE anywhere in the tree
sis query doc.pdf "**[polyglot=true]" # nodes in a polyglot
Output envelope: { "result": { "type": "asset_select", "source": "asset_graph", "matched_count", "nodes": [...] } }. A selector runs live (sis query <file> "<selector>") or over a
saved report without rescanning (sis query --from-report report.json "<selector>").
Predicates
[field=value] filters matched nodes on typed asset fields. Supported fields:
format— the sniffed format (pe,pdf,zip,png,js, …). This is what routing keys on.shape— the structural identity (container.zip,markup.html,script.js, …): the source-qualified structural authority’s answer to “what is this artefact?”. Distinct fromformat(the coarse sniff) —[shape=…]matches only where a shape probe structurally resolved that format. One answer per node, even on a polyglot.candidate_shape— membership over every accepted shape candidate. Where[shape=…]asks what the artefact is,[candidate_shape=…]asks whether a format was accepted at all, so a polyglot’s non-selected views stay queryable: a PDF carrying a script-shaped member matches both[shape=document.pdf]and[candidate_shape=script.vbs].extent— the honest validation depth of any shape candidate (magic,header,header_and_footer,index,physical_layout,whole_structure, …).[extent=header]= shallow-validated members.origin—root/email_part/archive_entry/embedded_object/carved.depth— nesting depth (numeric:>=,=,>,<,<=).complete—true/false(a truncated/over-budget member isfalse).analysis_state,declared_type,sniffed_type.finding— membership:[finding=<kind>]matches nodes carrying that finding kind.sha256/blake3— the decoded-content digest (the content address is blake3).polyglot—trueiff the node is a polyglot container or sits inside one.polyglot_views— interpretation count on a polyglot node (numeric).view— scope to one polyglot interpretation, e.g.[view=zip].
sis query sample.eml "**/[format=pe]" # executables at any depth
sis query sample.zip "**/[format=ooxml][complete=false]" # truncated OOXML members
sis query doc.pdf "**/[format=pe][polyglot=true]" # a PE inside any polyglot
sis query doc.pdf "**/[format=pe][view=zip]" # scoped to the zip interpretation
sis query bundle.zip "**/[shape=container.ooxml]" # members whose structural identity IS OOXML
sis query bundle.zip "**/[candidate_shape=container.zip]" # members where ZIP was accepted as any candidate
sis query bundle.zip "**/[extent=header]" # only header-deep (shallow) structural members
Terminals
A trailing /<terminal> projects something about the matched nodes:
/findings— the findings attributed to each node./summary— a compact per-node summary (path, format, counts)./sha256— the decoded-content digest (reported asblake3+digest_algo)./views— for a polyglot node, its interpretations (view_format, verdict, finding count)./text— each matched asset’s extracted safe-text (live scan only — a saved report carries handles, not bytes, so--from-report … /textrefuses)./bytes— write each matched asset’s decoded bytes to disk. Egress-gated: refuses without--extract-to <dir>(raw member bytes never go to stdout) and in report mode. Returns a manifest (asset_path,output_path,size,blake3) — never inline bytes.
sis query bundle.zip "**/[format=ooxml]/text" # per-member safe-text
sis query bundle.zip "**/[format=pe]/sha256" # per-member digest
sis query doc.pdf "**[polyglot=true]/views" # interpretations
sis query bundle.zip "**/[format=pe]/bytes" --extract-to /tmp/out # carve out the PEs
Scope note: /text and /bytes resolve for the root and first-level container members (the flat
member seam); deeply-nested members report unavailable honestly.
Polyglots
A polyglot is one asset whose bytes parse validly as multiple formats. It is modelled as a single node
with one interpretation subtree per format. Selectors are transparent through the polyglot
wrapper: zip/pdf reaches a PDF via zip → (polyglot) → pdf without naming the polyglot. Query for
polyglot relationships with [polyglot=true], [polyglot_views>=2], [view=<fmt>], and /views.
Related guides
sis docs query— the fullsis querynamespace +--wheregrammarsis docs shape— clustering files by asset-graph shape (campaign hunting)sis docs extract—extract --asset <selector>scoped extractionsis docs cdr—sanitize --asset-selectorscoped-drop planning