SIS CLI

Extract Guide

sis extract recovers the textual content of a document — the body/metadata text a human, a renderer, a retriever, or a model would actually see — format-agnostically and without scoring or a verdict. It is a provenance-aware, hostile-aware text extractor (a channel-aware extractor), not an analysis command: it never decides whether content is malicious. Use sis scan/sis assess for that.

When to use it

  • Feed a document’s text into a RAG pipeline, a model, or a search index — with explicit channel selection and removal limits.
  • See which text is visible vs. hidden/retrieval-only (the channels an injection hides in).
  • Remove spans identified by the configured removal contracts before ingestion (--safe), with a logged, deterministic removal contract.

Channels

Extraction is organised into typed channels. The default emits body,metadata; other classes are counted but not emitted unless you ask for them:

  • body — text attributed to the body by the extractor; attribution is not rendering proof
  • metadata — title/author/XMP and other document metadata
  • annotation — annotation/comment text
  • embedded — text from embedded objects
  • hidden — render-suppressed / retrieval-only text (the prime prompt-injection carrier). Counted by default, not emitted — select it explicitly (--channels hidden or --include-hidden) to see it.
  • code — script/macro text
  • all — every class

Channels classified as hidden are emitted separately when selected. Classification can be incomplete: the HTML limitation below shows that concealed text can also be attributed to body. Neither channel labels nor removal counts alone establish what a renderer would show or what remains safe to ingest.

Common invocations

sis extract report.pdf                          # markdown (YAML frontmatter), body+metadata
sis extract report.pdf --format json            # structured JSON (no frontmatter)
sis extract report.pdf --format text            # plain text only
sis extract report.pdf --channels all --include-hidden   # everything, hidden labelled
sis extract report.pdf --metadata-only          # metadata channels only

Safe text (AI-ingestion)

--safe strips the spans flagged by the safe-text removal contracts: text carried by hidden or transformed instruction carriers. Visible directive-like text is passed through unchanged. The analyser does not judge the meaning of visible prose, so a visible “ignore previous instructions” is a non-verdict fact, not a removal; filtering it is the consuming guard’s job. The result is a derivative with disclosed removals, not proof that all harmful instructions were found:

sis scan doc.pdf --format json --emit json=report.json
sis extract doc.pdf --safe --from-report report.json     # deterministic: contracts from the report
sis extract doc.pdf --safe                                # minimal inline analysis derives contracts
  • --from-report <REPORT> makes the removal deterministic (same bytes + options ⇒ identical output) by reading the contracts a prior sis scan --format json produced. Use it only with the exact unchanged input that produced the report. The current extractor does not verify report/input identity; the caller must bind them. Keep both input/report digests and the build/options with the derivative.
  • Without --from-report, --safe runs a minimal inline analysis to derive the contracts (the verdict is discarded). It fails closed if no contract source is available — it does not silently fall back to faithful extraction when contract acquisition fails. A successful contract acquisition still does not establish complete observation coverage.
  • --safe-min-confidence <tentative|probable|strong|certain> (default probable) is the minimum confidence of a flagged span to remove. Raising it can retain lower-confidence flagged spans; it does not raise the assurance of the remaining text.

Known HTML limitation: text from a render-hidden node can be retained in a body channel even with --safe/ai-ingest-safe, while removal telemetry reports applied removals. A removal count is not proof that the emitted text excludes every flagged instruction. Inspect the actual channels, and refuse the original or derivative when your ingestion policy cannot accept that uncertainty.

Named extraction profiles

sis extract sample.html --profile human-visible --format json
sis extract sample.html --profile ai-ingest-safe --format json
sis extract sample.html --profile analyst-full --format json

human-visible selects body/metadata; ai-ingest-safe selects those channels plus identified span removal; analyst-full selects all channel classes including hidden/code/embedded. The detector-substrate profile additionally exposes raw/non-content material. Profiles conflict with explicit --channels and --metadata-only. Profile names describe presets, not safety certification. Inspect the emitted removal and unavailable-channel records before ingestion.

Containers and batch

  • --members <inline|root-only|separate> projects container members (email attachments, archive entries, OOXML parts). inline (default) folds member channels into one document; separate emits one document per member (bounded by --max-depth, default 4); root-only suppresses members.
  • --path <DIR> [--glob PATTERN] [--jobs N] batch-extracts every matching file, streaming JSONL (--format jsonl). Format is detected from content, not extension.

Determinism

Extraction is deterministic: the same bytes + the same options (+ the same removal-contract source and engine build) define the extraction conditions. Preserve removal records, coverage and input identity when comparing outputs. --posture is a recorded label; it does not select the inline scan policy. Do not infer cross-version or cross-environment equivalence from it.

Scoping to specific assets (--asset)

--asset <selector> scopes extraction to the assets matching an asset-path selector, extracting each matched member as its own document instead of the whole root. It reuses the same selector engine as sis query and the same channel/--safe/--format pipeline, applied per selected asset.

sis extract bundle.zip --asset "**/[format=ooxml]" --format json   # just the OOXML members' text
sis extract report.pdf --asset "pdf:root"                          # the root document only

Do not combine --asset with --from-report: the asset path uses the live per-asset pipeline rather than the report-backed root path.

Single-file only (conflicts with --path batch and --members separate — the selector is the member scoping). A no-match selector exits non-zero, and so does a selector that cannot be decided for a selected asset (it tests a field the asset never recorded): extraction refuses and acts on nothing rather than extract a partial selection. Deeply-nested members beyond the flat member seam report status: unavailable. The selector grammar is in sis docs asset-graph.

What it does NOT do

  • No verdict, no findings, no scoring — use sis scan / sis assess.
  • No file rewrite — it emits text, not a sanitised document. To produce a cleaned file, use sis sanitize (CDR). sis docs cdr.
  • sis docs assess — the AI-ingestion decision that wraps safe-text
  • sis docs cdr — produce a cleaned file (not just text)
  • sis docs asset-graph — the --asset selector grammar (and /text in sis query)
  • sis docs formats — which roots are supported
  • sis docs scan-config — analysis options (extract is analysis-free, but scan feeds --from-report)