Please report suspected vulnerabilities privately via GitHub's private vulnerability reporting on this repository. Do not open public issues for security reports. We aim to acknowledge reports within 72 hours.
All application windows run with the full Electron renderer lockdown:
contextIsolation: true,nodeIntegration: false,sandbox: truefor every document window and tab view (docs, sheets, slides, pdf, shell, updater).- Renderers reach the main process only through typed, validated IPC channels (payloads are schema-checked in the main process; sheets uses zod end to end).
- Every
shell.openExternalcall goes through a single shared gate (@hermesoffice/electron-utils→safeExternalUrl) that parses the URL and enforces a protocol allowlist (http/https; pdf link annotations additionally allow mailto).file:,javascript:, and custom schemes are always rejected. - No API keys are hardcoded. AI requests are proxied through the signed-in account by default; user-supplied keys stay in the OS-level settings store.
The slides AI can adjust slide layouts by emitting a small script that is
parsed with Acorn and evaluated by a constrained AST interpreter
(apps/slides/src/renderer/ai/layout-script-interpreter.ts). The source looks
like a small, synchronous subset of JavaScript for model compatibility, but it
is not passed to eval, Function, a VM context, a worker, or the JavaScript
engine as executable source.
What the script can do by design: read prototype-free JSON copies of
els/canvas, perform bounded arithmetic/control flow, use explicitly
implemented string/array/regular-expression/Math helpers, and call
setBox/moveBy/resizeBy/setText/setStyle/setFill/setStroke/log. Every edit
primitive validates its arguments (element existence, read-only flags, finite
numbers, hex colors) and writes only into an op buffer that is applied through
the same command pipeline as manual edits.
Interpreter boundary:
- Identifiers resolve only in interpreter-owned lexical scopes seeded with the documented data and callables. There are no ambient globals, module loader, DOM, network, IPC bridge, timers, process APIs, or dynamic code primitives.
- Property reads are dispatched by value type. Data objects expose own JSON fields only; arrays, strings, and regexes expose a small method allowlist. Host prototypes and function properties are never traversed, including through computed property names.
- Calls accept only interpreter-created functions or explicit builtins. A host function obtained through a constructor/prototype chain cannot be represented.
- Inputs and values crossing into edit primitives are recursively copied as JSON-like, prototype-free data. Errors discard all buffered operations; logs are capped.
- Execution has statement/expression and call-depth limits to bound runaway loops or recursion.
The Electron renderer sandbox remains defense in depth, but it is not the layout-script security boundary. The interpreter is designed so a layout script cannot obtain renderer capabilities in the first place.
If you find a way for a layout script to reach anything beyond the injected primitives (network, storage, IPC channels not reachable by design, or the main process), that is a vulnerability — please report it.
The HTML-to-pptx export pipeline renders AI-generated HTML in a hidden
BrowserWindow. That window is treated as hostile content: full renderer
lockdown (sandbox: true, contextIsolation: true, nodeIntegration: false),
no preload script, no IPC surface — the main process drives it exclusively
through executeJavaScript and destroys it under a watchdog timeout.
- The cloud AI services this client talks to are operated separately and are not part of this repository; issues with them should be reported through the service provider's channels.
- Vulnerabilities that require an already-compromised machine or a modified
binary. This includes the deliberate environment-variable override points
for local development (
GSK_CLI_PATH,XLSX_SIDECAR_PATH): setting them requires control of the process environment, which is equivalent to code execution on the machine.