Plugins (advanced)
A tile plugin is the most powerful custom tile: a self-contained HTML
- JavaScript widget that renders inside a locked-down sandboxed iframe, while Saiku feeds it the tile’s query rows. Use it when neither the built-in tiles nor the declarative custom renderers can draw what you need — a bespoke gauge, an unusual layout, a purpose-built widget.
Plugins are an advanced, administrator-controlled feature. This page is mostly about their trust model, because getting that right matters more than the mechanics.
How a plugin is installed
An operator (not a dashboard user) drops a bundle into a folder on the Saiku server:
${saiku.home}/tile-plugins/ records-bars/ plugin.json # id, label, and an optional option schema plugin.html # self-contained widget: inline CSS/JS, data: images onlyplugin.jsondeclares the plugin’sid(a slug likerecords-bars), a displaylabel, and optionally anoptionSchemadescribing the author-configurable options.plugin.htmlis the widget itself — a single self-contained HTML document with inline CSS and JavaScript (no remote scripts, styles, or fonts; images must bedata:URIs).
The server scans the folder and makes installed plugins pickable. A
dashboard author adds one from + Add tile, where each installed
plugin appears as its own entry; the persisted tile stores only the
plugin’s id, never any markup.
Saiku ships one seed example — records-bars, a simple records bar
chart — so a fresh install has a working plugin to look at and copy.
What the sandbox does — and does not — contain
Every plugin frame runs behind two containment layers.
1. An iframe sandbox="allow-scripts" (deliberately without
allow-same-origin). The frame runs at the opaque null origin, so
plugin code cannot:
- read the parent page’s DOM, cookies, or
localStorage; - see the Saiku session, an embed token, or any other-origin data;
- open popups, submit forms, navigate the top window, or trigger downloads.
2. A strict Content-Security-Policy on the frame
(default-src 'none', no connect-src). This blocks background
network egress — fetch, XHR, WebSocket, EventSource,
sendBeacon, remote subresources, and the classic
<img src="https://evil…"> beacon.
Closing the self-navigation channel
If you want to shut the self-navigation exfil channel too, an operator
sets a restrictive frame-src in the deployment CSP via
saiku.security.csp (at the reverse proxy or the launcher’s CSP config).
Constraining where plugin frames may navigate is the only way to govern
navigation — the per-tile sandbox and CSP cannot, by design.
The plugin ↔ host protocol
The host and plugin communicate only through window.postMessage. On
mount, the host injects a per-frame cryptographic nonce; every
message a plugin sends must echo that nonce or it’s dropped (a
sandboxed frame’s origin is the string "null", so the nonce is the only
trustworthy authenticator).
- Host → plugin:
init(the author’s options),data(the query records),theme, andresize. - Plugin → host:
ready(I’ve loaded),resize(please set my height — clamped by the host),filter(a selection, which the host re-resolves against the live cube — a plugin can’t inject MDX), anderror(rendered as plain text only).
The host validates and clamps everything a plugin sends; a malformed or unauthenticated message is ignored rather than acted on.
Plugins in embedded Apps
When an App is embedded, its plugin tiles are
served token-scoped: a guest can load exactly the plugins referenced
by the embedded App’s tiles and nothing else. The same sandbox + CSP
containment applies, and the same self-navigation caveat holds — so the
frame-src guidance above is the operator control for embedded Apps too.
Related
- Custom tiles — the safer, code-free declarative renderers; reach for a plugin only when those can’t.
- Embedding an App — how token-scoping applies to plugin tiles.
- How your data is handled — the wider data-handling model.