You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Decision needed: is the extension permission model a security boundary, or trusted-code metadata?
This is a design discussion, not a task — it's a strategic fork that shapes the
extension platform, so it doesn't fit the atomic-issue model the other improve
issues (#25–#35) use.
The situation
Generated extensions are loaded with await import(url.href) in the Electron main process (src/electron/main.ts, loadExtensionModule/loadExtensions).
That means extension code runs as fully-privileged Node/Electron code at module
import time — before any permission check runs. Permission gates only affect the
host-provided ctx capabilities, not what top-level extension code can already do.
Consequence: an extension's permissions: [...] manifest is declarative UX, not
a security boundary. A malicious or AI-misgenerated extension can read/modify the
filesystem, process env, auth state, app memory, spawn child processes, and reach
host internals regardless of what it declares — by running code at import, before
gates apply.
This was flagged as the top item (Critical #1) in the 2026-06-03 security audit
(.plans/security-audit-report.md) and re-confirmed still open at commit e581e95.
Why it's a fork, not a bug fix
The product thesis is "the AI writes your extensions." So the right answer depends
on a product/trust decision, not just engineering:
Option A — accept it (treat extensions as trusted code):
Document explicitly that extension permissions are UX/declarative metadata, not
a sandbox.
Move the security boundary to who/what can author extension files (e.g. only
the app's own AI flow writes them; guard the extensions directory; consider
signing/integrity checks).
Lowest effort; honest about current reality. Risk: as soon as extensions can
come from anywhere (sharing, marketplace, copy-paste), the trust assumption
breaks.
Option B — sandbox generated extensions:
Run extension code in an isolated runtime with no Node/Electron primitives
(e.g. a locked-down worker/vm/separate process with no require/import of
host modules).
Expose only typed host RPCs from main, with permission checks enforced at every
capability boundary.
Highest effort, but makes permissions: [...] a real boundary and lets
untrusted/shared extensions be safe.
Questions to resolve
Will extensions ever come from outside the app's own AI generation (sharing,
import, a marketplace)? If yes, Option A's trust assumption is temporary.
Is permissions: [...] meant to protect the user from the extension, or just
to describe capabilities? Today it implies protection it doesn't provide.
If Option B: what's the minimal viable sandbox (worker vs separate process vs
vm), and what's the host-RPC surface?
Suggested next step
A short design spike: pick Option A or B, and if B, prototype the isolated runtime
host-RPC surface and list open questions. The outcome becomes concrete
implementation issues.
Related hardening already shipped: extension window sandboxing, webview
permission allowlist, navigation policy (these reduce blast radius but do not
close the import-time execution path).
Decision needed: is the extension permission model a security boundary, or trusted-code metadata?
This is a design discussion, not a task — it's a strategic fork that shapes the
extension platform, so it doesn't fit the atomic-issue model the other
improveissues (#25–#35) use.
The situation
Generated extensions are loaded with
await import(url.href)in the Electronmain process (
src/electron/main.ts,loadExtensionModule/loadExtensions).That means extension code runs as fully-privileged Node/Electron code at module
import time — before any permission check runs. Permission gates only affect the
host-provided
ctxcapabilities, not what top-level extension code can already do.Consequence: an extension's
permissions: [...]manifest is declarative UX, nota security boundary. A malicious or AI-misgenerated extension can read/modify the
filesystem, process env, auth state, app memory, spawn child processes, and reach
host internals regardless of what it declares — by running code at import, before
gates apply.
This was flagged as the top item (Critical #1) in the 2026-06-03 security audit
(
.plans/security-audit-report.md) and re-confirmed still open at commite581e95.Why it's a fork, not a bug fix
The product thesis is "the AI writes your extensions." So the right answer depends
on a product/trust decision, not just engineering:
Option A — accept it (treat extensions as trusted code):
a sandbox.
the app's own AI flow writes them; guard the extensions directory; consider
signing/integrity checks).
come from anywhere (sharing, marketplace, copy-paste), the trust assumption
breaks.
Option B — sandbox generated extensions:
(e.g. a locked-down worker/
vm/separate process with norequire/importofhost modules).
capability boundary.
permissions: [...]a real boundary and letsuntrusted/shared extensions be safe.
Questions to resolve
import, a marketplace)? If yes, Option A's trust assumption is temporary.
permissions: [...]meant to protect the user from the extension, or justto describe capabilities? Today it implies protection it doesn't provide.
vm), and what's the host-RPC surface?
Suggested next step
A short design spike: pick Option A or B, and if B, prototype the isolated runtime
implementation issues.
References
src/electron/main.ts—loadExtensionModule/loadExtensionssrc/electron/extension-permissions.ts— current permission gating (ctx-level).plans/security-audit-report.md— finding [ImgBot] Optimize images #1 (Critical)permission allowlist, navigation policy (these reduce blast radius but do not
close the import-time execution path).