| 1 | /** |
| 2 | * webPreferences override applied to every preview `<webview>` element via |
| 3 | * its `webpreferences="..."` attribute. Single source of truth so all guest |
| 4 | * surfaces inherit the same security posture. |
| 5 | * |
| 6 | * Lives in its own electron-free module so the value is unit-testable |
| 7 | * without importing `Manager.ts` (which transitively imports |
| 8 | * `electron` and blows up under vitest). |
| 9 | * |
| 10 | * - `contextIsolation=false`: the picker preload needs to share `globalThis` |
| 11 | * with the page so react-grab/bippy can read the React DevTools hook |
| 12 | * (`__REACT_DEVTOOLS_GLOBAL_HOOK__`) and resolve component names. Without |
| 13 | * this every pick comes back with `componentName: null` even on dev React |
| 14 | * apps. |
| 15 | * - `sandbox=true`: keeps the OS-level renderer sandbox enabled. Critical |
| 16 | * when paired with `contextIsolation=false` — without sandbox, the preload |
| 17 | * has full Node access (`require`, `fs`, `child_process`, ...) and that |
| 18 | * `require` would land on the page's shared `globalThis`, giving any |
| 19 | * third-party page in the preview full Node + IPC access to the host. |
| 20 | * In sandboxed mode Electron still synthesizes the `electron` module for |
| 21 | * the preload's `import { ipcRenderer }` line, but no Node globals leak. |
| 22 | * - `nodeIntegration=false`: pinned for clarity (the page itself never gets |
| 23 | * Node access). |
| 24 | * |
| 25 | * Format notes (locked down by `WebviewPreferences.test.ts`): |
| 26 | * - Whitespace-free. Electron's webpreferences parser splits on `,` and |
| 27 | * does not trim, so a leading space would turn a key into an unknown one |
| 28 | * and silently drop it. |
| 29 | * - Values are JS-boolean strings (`true`/`false`) — `yes`/`no` are not |
| 30 | * special-cased by the parser; `value="no"` becomes the truthy STRING |
| 31 | * `"no"` when assigned to a boolean webPreferences key. Most critically, |
| 32 | * `contextIsolation="no"` is truthy → contextIsolation stays ENABLED → |
| 33 | * react-grab can't see the React DevTools hook. |
| 34 | * |
| 35 | * Defense in depth: `apps/desktop/src/main.ts` also runs a |
| 36 | * `will-attach-webview` handler that force-sets `sandbox: true` and |
| 37 | * `nodeIntegration*: false` on the actual webPreferences object, gated on |
| 38 | * the preview partition, so even if this string is ever wrong, the |
| 39 | * security-critical flags can't regress on preview tabs. |
| 40 | */ |
| 41 | export const PREVIEW_WEBVIEW_PREFERENCES = |
| 42 | "contextIsolation=false,sandbox=true,nodeIntegration=false"; |