Security model
The editor is a local web server that can write files, so it is locked down by default. To report a vulnerability, see SECURITY.md.
- The server binds
127.0.0.1with a random port and a per-run token. The token is exchanged for anHttpOnly; SameSite=Laxcookie named after the port (df_token_<port>), so several editors can run side by side. The cookie isLax, notStrict, because some hosts (the GitHub Copilot app's built-in browser, for example) open the URL from another site: browsers drop aStrictcookie on that first redirect and the editor answers 401.Laxonly adds the cookie to top-levelGETnavigations, which don't change anything. Writes still need a same-origin (or absent) Origin header and a JSON body, so a cross-site form orfetchcan't use the cookie. - The server checks the Host header against DNS rebinding and the Origin header on writes. It requires JSON request bodies and sends a strict Content-Security-Policy for the editor.
- Writes happen only in the deck folder (
deck.yaml,deck.html,deck.pptx,deckforge/,templates/,assets/) and in~/.config/deckforge/(templates/and the Copilot handoff files below), plus thedeckforgeentry of~/.copilot/mcp-config.jsonwhen you ask for it. Dot-files and paths outside the deck folder are never served. - Uploads (
POST /api/assets) need the token, pass the Origin check and are limited to 10 MB. The file type comes from its magic bytes, never from its name or Content-Type. SVG files with scripts, event handlers,javascript:URLs,foreignObjector entity declarations are refused. Files are stored asassets/<sha256-12>.<ext>. Assets are served withX-Content-Type-Options: nosniff, and SVG with asandboxContent-Security-Policy. User images are always<img>elements, never inline SVG. The server never fetches remote URLs. - PowerPoint export (
POST /api/export/pptx) needs the token and passes the Origin check. It accepts only a ZIP package up to 200 MB and always writesdeck.pptx(named afterdeck.yaml) next to the deck. The browser builds the file from the laid-out deck; the server never parses it. - Slot text is HTML-escaped and rich text is sanitized with an allow-list. Theme values are validated.
- deckforge sends no telemetry.
The Copilot assistant
- Copilot can only use deck tools. It has no shell, file or web tools, and every other permission request is refused.
- It places only images that are already in
assets/. It never downloads anything. deckforge mcpgives MCP clients the same deck tools. To reach a running editor, it reads a private record (~/.config/deckforge/editors/<id>.json, mode 0600) that holds the editor's loopback address and token.deckforge editdeletes the record when it stops. Tool calls send the same token as the browser, and they are refused while the editor's own Copilot turn is running.- The editor remembers the last Copilot session ID of each deck in
~/.config/deckforge/sessions.json. It writes the MCP configuration for Continue in Copilot to~/.config/deckforge/mcp/. Neither is written in the deck folder. - Only when you ask (Add the deck tools to Copilot, or
deckforge mcp --install) does deckforge write to~/.copilot/mcp-config.json, and then only its owndeckforgeentry. Open in Copilot app opens aghapp://sessions/<id>link built from a validated session ID, and the app asks you to confirm.