Skip to content
Versionv0.1 ALPHA 2

Viewer plugins

Architecture - in development

The plugin system described here is the Viewer's plugin architecture and security model. The signed-registry, verification, and capability mechanisms are part of the design; not every control is generally available yet. This page documents how plugins are designed to load and run.

Plugins extend the Viewer's rendering and verification UX - new previews, inspectors, annotations, organizational controls - without weakening the trust model. The plugin system is built on the same principle as the OSDF container: every byte is declared, and nothing undeclared loads.

Signed registry and manifest

Every plugin ships with a manifest and a publisher signature. The manifest enumerates each file in the plugin and its SHA-256 hash, the permissions the plugin requests, and publisher identity. On load, the Viewer:

  1. Recomputes the SHA-256 of every file and compares it to the manifest.
  2. Verifies the publisher signature over the canonical manifest.
  3. Rejects any file present on disk but not declared in the signed manifest.

This is fail-closed: a corrupted, tampered, unsigned, or signature-mismatched plugin does not load. There are no hidden or undeclared files - anything not in the signed manifest is treated as tampering, exactly like an undeclared object in an OSDF package.

Always up to date

When the Viewer is signed in, it checks the registry for the current approved versions of installed plugins. Based on policy it will:

  • Flag outdated plugins and surface the approved version.
  • Auto-update to the approved version, or block a stale version from loading, according to org policy.
  • Honor revocation - a plugin marked revoked in the registry is pulled everywhere it is installed. Central revocation means a compromised plugin can be withdrawn fleet-wide, not patched device by device.

Offline, the Viewer continues to enforce the last known registry state (including revocations) and fails closed on anything it cannot positively verify.

Capability and permission model

Plugins declare the permissions they need; the Viewer enforces least privilege. A plugin runs sandboxed with no ambient filesystem or network access - it can only do what its manifest declares and what org policy permits. The default posture is passive: plugins extend rendering and verification UX, they do not execute arbitrary code or reach outside their grant.

CapabilityAllowsDefault
render.hookRegister custom render/preview surfaces for declared media typesPassive, in-sandbox
verify.hookAdd verification-result UI (badges, inspectors) over core resultsRead-only
file.readRead the currently open document's declared objectsScoped to active doc
file.read.workspaceRead other local files the user explicitly selectsOff - opt-in
network.fetchReach an allowlisted endpoint (e.g. a revocation or policy service)Off - declared hosts only
clipboard.writeCopy verification output / citations to the clipboardOff - opt-in
storage.localPersist plugin settings in a sandboxed, per-plugin storeSandboxed
policy.enforceApply org controls (e.g. watermarking, DLP) over renderingManaged mode only

A plugin that requests no network capability cannot make a network call, even if it tries - the sandbox denies access that was not declared and granted. Org policy can further narrow any grant; see Plugin governance.

Example manifest

The manifest below is illustrative. Hashes and the signature are computed over the canonical bytes of the declared files and the manifest payload, respectively.

json
{  "id": "com.example.redaction-inspector",  "version": "1.4.0",  "publisher": "Example Security, Inc.",  "permissions": [    "render.hook",    "verify.hook",    "file.read"  ],  "files": [    { "path": "main.wasm", "sha256": "9f2b1c7d4e8a0b3f6c5d2e1a8b7c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c" },    { "path": "ui/panel.js", "sha256": "3a1f0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3928170615243342516071829a" },    { "path": "manifest.json", "sha256": "c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3" }  ],  "signature": {    "alg": "Ed25519",    "key_id": "example-sec-2026-01",    "value": "MEUCIQ...base64...A0b9c8d7e6f5"  }}

If any file's recomputed hash differs from files[].sha256, or the signature does not verify under the publisher key, or a file exists that is not listed in files[], the Viewer refuses to load the plugin.

Related

Spec status: working draft v0.4 · subject to change before v1.0.