Security & architecture

How it works, and why your file never leaves your machine.

The deep-dive for the technical evaluator. The homepage stays tight; this page is where the structure of the trust model lives.

The local-first model

PayloadGlass analyzes files where they already are. In a deployment, the engine runs on your own infrastructure. In the browser workbench, the same production analysis engine is compiled to WebAssembly and runs entirely in a Worker in your own tab — the analysis path has no backend to send a file to. The page loads its own app assets, and it fetches a sample if you pick one, but your file's content, its name, and the derived report are never transmitted — file-content egress is zero. You can verify it: open your browser's network panel and confirm no request carries your file. Once the page and its engine have loaded, you can disconnect and analysis of a file you already have still runs. We do not describe the product as "fully offline": loading it needs the network, and persistence, if you turn it on, is local to your browser.

What the engine actually does

The SIS engine parses a file's real structure rather than a flattened preview: the recursive object graph, embedded and nested objects, active content (scripts, macros, actions), and the parser-level tricks that text-only filters and LLM guardrails often do not see. Findings carry registered identities and an evidence span — the byte range or node that triggered it — plus the coverage of the parse and the policy that acted. Verdicts expose a structured decision trace you can inspect, rather than a bare score. (Typed evidence signals are being rolled out lane by lane; not every finding carries one yet.)

Threat assessment, and everything that qualifies it

A single "malicious / clean" label hides the fact that risk depends on what you are about to do with the content, and on how it reached you. We deliberately do not publish a fixed count of "axes" — the model is extensible, and freezing a number into marketing would be a promise we'd rather not make. What matters is the split:

Threat assessment — what drives the security verdict

  • Hostility — could this harm a system, user or agent by executing, exploiting, fetching, evading or chaining?
  • Deception — does it manipulate a person into an unsafe action? (QR lures, fake login, ClickFix, brand impersonation)
  • AI-ingestion — could it corrupt or manipulate a model, retrieval or agent workflow? (hidden prompts, retrieval-visible instructions, tool-use directives)

The security verdict (malicious / suspicious / benign) is the worst of those three. Nothing below changes it.

Decision context (target; partly built) — what changes the answer without changing the verdict

  • Sensitivity — secrets, credentials, PII and confidential material found locally, evidence-safe and verdict-inert.
  • Custody — how it arrived: sender, origin, sharing scope, quarantine state, who handled it.
  • Consumer and action — a reader, a renderer, a retrieval indexer and an agent are exposed differently by the same capability.
  • Tool and data privileges — what the consumer is actually allowed to do with what it reads.
  • Integrity and authenticity — what is genuinely bound or verified, as distinct from what the file merely claims.
  • Lineage — what was derived from what, across a nested chain.
  • Intended destination — open locally, index, forward, or hand to a tool.

A note on vocabulary: we avoid the unqualified word "provenance", because it conflates at least three different things — custody, lineage, and integrity/authenticity. They have different evidence and different failure modes, so we name them separately. Where the engine emits contradiction findings across a nested chain, that is evidence about the file's own claims — not cryptographic proof.

Where this stands: the three verdict-driving assessments ship, and the secret/PII detection feeding sensitivity ships (evidence-safe, verdict-inert, local). Sensitivity is advisory and gates nothing today. Custody and consumer/action are being built as canonical contracts — today they are distributed across surfaces rather than unified, and a bare scan has no acquisition context at all. The enforcing, coverage-qualified decision above them is the current work.

The rules the system holds itself to

These are load-bearing invariants, not implementation trivia. They are what make a finding mean the same thing on the command line, in CI, in the browser and on the desktop.

  • Unknown is not clean. Unsupported, not run, not measured, incomplete, budget-limited and failed are distinct states, and the product is built to keep them visible. This holds in lanes that have a member producer and a coverage record. Two known gaps: some formats (for example HTML, images, fonts and other binaries) do not yet enumerate members and report traversal as complete, and most analysis budgets do not yet record their own exhaustion. Both are being closed, and until they are, a clean-looking report is not proof that everything was examined.
  • Route is not identity. Several exact formats may share one analysis lane; the exact format and every accepted interpretation are retained rather than collapsed into one guess.
  • Evidence timing matters. Evidence shown beside a verdict is not presented as having influenced it unless it existed when that verdict was taken.
  • Projection is not authority. Browser, desktop, reports and gateways consume shared contracts; they never redefine what a finding means.
  • Nested lineage survives. A finding discovered several layers deep keeps its native identity and derivation when lifted into the parent investigation.
  • Operations are revision-bound. An action is requested against an exact subject and revision, so it cannot silently act on replaced bytes or stale authority.

What we support, and how well.

We publish support per root and capability — recognition, structure, parser, member enumeration, text channels, safe-text, sanitisation and sensitivity coverage — rather than a detector count that says nothing about whether your file is covered.

The full per-format table is on the supported formats page →

Native roots

PDFOffice OOXMLOLE compound filesRTFHTML / HTAMHT / MHTMLZIPISO / UDFPEELFLNKstandalone scripts

Partial and embedded surfaces

Depth varies here. Several of these also have a native lane declared in the registry; the supported formats table lists what is declared, and neither list grades depth.

EmailOneNoteCSS / LESSadditional archivesimagesfontsrich media

And the states that are neither

Coverage is not one percentage or a traffic light. Anything unsupported, not run, not measured, incomplete, budget-limited or failed is meant to stay in its own state rather than fold into a pass. That holds today where a coverage record exists; see the known gaps in the rules above.

unsupported not run not measured incomplete budget exhausted failed

The container image, and exactly what its attestation covers

The sis CLI is also published as a multi-architecture OCI image at ghcr.io/payloadglass/sis. It is worth being precise about what that image is, because container supply-chain language is routinely oversold.

  • It is assembled, not rebuilt. The image repackages the Linux archives the release already published. There is no source, no toolchain and no compilation step in it — so publishing it exposes nothing the release does not.
  • The attestation names the assembly workflow as the builder. It attests that this image was assembled from those exact published bytes. It is not a cryptographic tie back to a source commit, and we will not present it as one. The runtime base is digest-pinned, the archives are checksum-verified before unpacking, and the assembly step is Sigstore-signed and recorded in a public transparency log.
  • The inputs are verified before they are trusted. Archives are checked against the published checksum manifest before unpacking, and the runtime base is pinned by digest — a floating base tag would let two runs of the same release produce different images with nothing recording the difference.
  • There is no rolling tag. Tags are release tags; there is no rolling tag. Pin by digest for reproducible runs. An image that silently changes under a stable name is not something you can attest about.
  • It runs unprivileged. Runs as a non-root user with no shell entrypoint, and works with a read-only root filesystem — mount the content you want analysed and nothing else.

The image runs the same engine as the CLI, so every local-first property above holds: analysis happens in your environment, and the example invocation drops the network entirely.

Transform: the safe-text derivative

Inspection is only half the job. Where policy calls for it, the engine emits a safe-text derivative — a model-safe version of the document with active content and hidden channels removed, paired with a log of exactly what was stripped, what was preserved, and what residual risk is still flagged. This ships today and is distinct from full content disarm & reconstruction (CDR), whose broad reconstruction guarantees are still hardening. The derivative never silently rewrites: every change is evidenced, which is what makes "prove what remains" a literal artefact rather than a slogan.

WASM & cross-origin isolation

The workbench runs the engine as WebAssembly, and where it relies on threads and SharedArrayBuffer for performance, the browser requires the page to be cross-origin isolated. That deploy therefore serves:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Content-Type: application/wasm   (for .wasm assets)

Those headers live on the separate workbench deploy (workbench.payloadglass.com), not on the marketing site.

Sample files in the workbench

The bundled samples are crafted, controlled files that trigger detectors without being genuinely dangerous to the visitor, and they're labelled as such. The workbench never needs — and you should never feed it — a live, genuinely dangerous malware sample.

Want to see it rather than read about it?

Open the investigation workbench →