Skip to content

Commit 509aee1

Browse files
committed
docs(plugins): grade the security debt against the code
Two of the five bullets overstated the problem. The postMessage `'*'` is forced by null-origin sandboxing and both hosts already validated `e.source`; the real hole was the client trusting anyone, now closed. The CSP bullet is not a repair — there is no network permission on this surface to honour, so honouring one is a feature. Marks the grants bullet half fixed, and says what the remaining half needs: a hash of the served `.ui.js` in `UIPluginListItem`.
1 parent 3865b5d commit 509aee1

1 file changed

Lines changed: 28 additions & 10 deletions

File tree

planning/plugins.md

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -306,16 +306,34 @@ Front-end plugins already ship (#1197), and today they are the weakest
306306
boundary in the system — more practical authority than server-side WASM, with
307307
less review:
308308

309-
- iframe CSP is `connect-src *` regardless of manifest; the `network`
310-
permission gates only server-side WASM.
311-
- Grants live at `atomic.plugins.ui.<namespace.name>` in local storage, keyed
312-
by neither drive nor artifact hash, so a same-named plugin on another drive
313-
or any replacement version silently inherits consent.
314-
- `postMessage` uses target origin `'*'` on both sides; messages are
315-
unvalidated and unversioned.
316-
- Implicit read scope includes anything parented under the page's `isA` class
317-
resources — intended for schema reads, actually a broad widening.
318-
- `pluginFile` changing auto-executes an install.
309+
- **Open.** iframe CSP is `connect-src *` regardless of manifest. Not a
310+
one-line fix: `PluginUIManifest` carries only `css`, so there is no network
311+
permission on this surface to honour — the `network` permission gates
312+
server-side WASM. Plumbing one in is a feature, not a repair.
313+
- **Half fixed.** Grants lived at `atomic.plugins.ui.<namespace.name>`, so
314+
consent given to a plugin on your drive was inherited by any plugin of the
315+
same name on a drive someone else shared with you. They are keyed by the
316+
plugin resource's subject now, which is unique per drive. Consent still
317+
survives the plugin's code being **replaced**, because nothing identifies
318+
the artifact; that needs the server to publish a hash of the served
319+
`.ui.js` in `UIPluginListItem`, which the client would fold into the key.
320+
- **Fixed, and it was misdescribed.** `postMessage` does use `'*'`, but it is
321+
forced: both frames are sandboxed without `allow-same-origin`, so every end
322+
is null-origin and there is no origin to name. Both hosts already validated
323+
`e.source` against the frame. The real hole was the other direction — the
324+
`@tomic/plugin` client accepted `message` events from anyone, so anything
325+
able to post into the frame could answer a pending request or push a
326+
`resource-notification` and hand the plugin a resource that does not exist.
327+
It checks `e.source === window.parent` now. Messages remain **unversioned**.
328+
- **Open.** Implicit read scope includes anything parented under the page's
329+
`isA` class resources — intended for schema reads, actually a broad
330+
widening. Narrowing it changes what already-installed plugins can see, so it
331+
wants a deprecation, not a patch.
332+
- **Open, and arguably by design.** `pluginFile` changing auto-executes an
333+
install — but only for someone who can already write the plugin resource,
334+
which is the rights model working. What makes it sharp is the artifact half
335+
of the grants bullet above: replace the code and the old consent still
336+
applies. Fix that and this mostly stops mattering.
319337

320338
This is cheap to fix now and expensive once third parties exist.
321339

0 commit comments

Comments
 (0)