Viewer plugins
Architecture - in development
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:
- Recomputes the SHA-256 of every file and compares it to the manifest.
- Verifies the publisher signature over the canonical manifest.
- 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.
| Capability | Allows | Default |
|---|---|---|
render.hook | Register custom render/preview surfaces for declared media types | Passive, in-sandbox |
verify.hook | Add verification-result UI (badges, inspectors) over core results | Read-only |
file.read | Read the currently open document's declared objects | Scoped to active doc |
file.read.workspace | Read other local files the user explicitly selects | Off - opt-in |
network.fetch | Reach an allowlisted endpoint (e.g. a revocation or policy service) | Off - declared hosts only |
clipboard.write | Copy verification output / citations to the clipboard | Off - opt-in |
storage.local | Persist plugin settings in a sandboxed, per-plugin store | Sandboxed |
policy.enforce | Apply org controls (e.g. watermarking, DLP) over rendering | Managed 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.
{ "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
- Plugin governance - org allowlists, mandated plugins, lockdown
- Integrity - document, plugin, and self-verification
- Security overview