Please report vulnerabilities privately via GitHub's private vulnerability reporting on this repository. Do not open a public issue. You should get a first response within a week; fixes ship as a patch release with a changelog entry.
Only the latest release is supported with security fixes.
pinax renders dashboards from config files (profile.json) that users write themselves, generate with an LLM, or import from strangers. The design assumption is that a profile is untrusted input. Three capabilities are therefore individually gated, per profile, and OFF by default:
| Gate | Unlocks | Risk it contains |
|---|---|---|
web |
iframe panes (https only) and "Import from URL" |
Loading remote content inside your vault window; fetching profile bundles |
command |
command-buttons panes |
Puts shell commands on your clipboard and opens a terminal. Commands are never auto-executed; the user always types/pastes and confirms in their own terminal |
write |
Forms, board drag & drop, actions, heatmap day-note creation, API note creation | Creating notes and rewriting frontmatter inside the vault. Every mutation shows an Undo notice |
Properties that hold regardless of gates:
- Zero-trust imports. An imported or duplicated profile always starts with all gates OFF, even if the profile it came from had them ON. Trust is keyed by profile id and never copied.
- Vault-relative paths only. Every path in a profile is validated twice (JSON Schema pattern at load,
safeVaultPathat read/write time): no absolute paths, no drive letters, no backslashes, no..segments. A profile cannot reach outside the vault through pinax's vault helpers. - No hidden network traffic. The core makes no network requests on its own. The only network activity is user-configured:
iframepanes and "Import from URL", both https-only and behind thewebgate. - No telemetry. The "Copy diagnostics" command only writes to the clipboard, contains configuration metadata (versions, pane types, trust booleans, validation errors), and runs only when the user invokes it.
- Failed validation fails closed. Invalid profiles render an error panel, not a partial dashboard; unknown widget ids render a placeholder, never code.
The community edition of pinax never executes code from your vault or from the network. Custom widgets come from companion plugins the user installs like any other Obsidian plugin; they register through the public window.pinax API (template in examples/companion-widget-plugin/). Profile bundles may still carry a widgets.js entry: it is stored as inert data for sharing (and for the feature/widgets-js development branch, which loads it behind an opt-in gate) and is never executed by released versions.
Releases are built by GitHub Actions from SHA-pinned actions, with build provenance attested via actions/attest-build-provenance. Verify an asset with:
gh attestation verify main.js --repo sphragis-oss/pinax