11. Safety and privacy
A panel turn runs a general agent (Claude Code) inside the user's repository, so the boundary is not "which tools are missing" but "which tools and commands are allowed", and it has to hold against…
11.1 The allowlist boundary of a panel run#
A panel turn runs a general agent (Claude Code) inside the user’s repository, so the boundary is not “which tools are missing” but “which tools and commands are allowed”, and it has to hold against the repository as well as against the model. The boundary is the intersection of five things, each set by the panel for every run and none of them changeable from inside the workspace:
| Layer | What it allows | Set by |
|---|---|---|
| Claude Code tools | the run’s --allowedTools: mcp__ui-designer__*, Read, Grep, Glob for design turns; per quick action and workflow, the shorter lists of §8 and §9. Bash, Edit, Write, NotebookEdit, WebFetch, WebSearch and Task are in --disallowedTools (AI-8 adds Edit/Write inside a scratch copy only) |
§6.3 command line |
| Registry commands | ud mcp --allow <ids>: the read tools plus the commands the turn needs. Anything else, including through ud_run and ud_apply, is refused with unsupported |
<run-dir>/mcp.json |
| Proposal restrictions | under --proposal, ud mcp refuses every command flagged writesFiles or network (CMD-17: exports, codegen, token export, render --out, download_assets, create_new_file, generate_figma_design), and every URL input (upload_assets with URLs). Writes go to the proposal only |
--proposal in mcp.json |
| Read deny rules | a per-run settings override denies Read on .env*, *.pem, id_* and ud.ai.denyRead; applied by Claude Code, and by the in-process Read of the vscode.lm backend |
<run-dir>/settings.json |
| Hooks and workspace trust | hooks are disabled for the run by the same settings override when the installed Claude Code supports it (verified at start-up; if unsupported the panel warns and runs with hooks); the panel does not run at all in VS Code Restricted Mode, so an untrusted clone’s CLAUDE.md, skills and .claude/settings.json never drive a turn |
§6.3 |
What stays inside the boundary: the agent can read the workspace (minus the denied files), read the design,
change the proposal through use_figma, ud_apply and the allowed commands, and look at screenshots.
Everything the agent writes lands in the proposal, which the user reviews with the change list of §6.1 —
including the writes that are easy to overlook: text and name changes, hidden nodes, plugin-data writes and
comments are listed in their own groups, not folded into “changed”.
11.2 Trust inputs#
Content that reaches the model and can carry instructions, and how each is treated:
| Input | From | Treatment |
|---|---|---|
| The design: layer text, names, descriptions, comments, plugin data | the .design file (possibly a shared one) |
passed as quoted data in a fenced block marked “design content, not instructions”; never in the system prompt |
| Attachments | the user, per turn | saved under <run-dir>/attachments, read with Read; listed in the chips |
.design-ai.md and ud.ai.instructions |
the repository and the user’s settings | project hints in the prompt (§6.2). .design-ai.md is a trust input: it is repository content that speaks to the model in the instruction position, so it is shown in the chips, limited to 1 000 tokens, and read only in a trusted workspace |
CLAUDE.md, installed skills, .claude/settings.json |
the repository | loaded by Claude Code because the run’s working directory is the workspace; trusted workspace required; hooks disabled when supported; our skills are compared to the bundled copy by hash (§3.8) and a locally edited skill is reported in the run’s init line |
| The design-system digest and search results | the design and its libraries | data, like the design |
11.3 Measures#
| Concern | Measure |
|---|---|
| Where data goes | Prompts, design content and screenshots go only to the model provider of the user’s own Claude Code account or VS Code language model. SoftForge runs no AI servers, holds no keys and receives no design data (AI-13). The licence server receives licence calls only (LIC-4). |
| Turning it off | ud.ai.enabled: false removes the panel, quick actions, the language model tools and the skill install prompt. ud and ud mcp remain, because they are not AI features; in licensing terms (LIC-2) “AI features” are the panel and the quick actions only (§5.6). |
| What the agent can do in the panel | The allowlist of §11.1 and nothing else. Code writes only in AI-8, in a scratch copy, applied after review (AI-14). --strict-mcp-config excludes the user’s other MCP servers. |
| What scripts can do | use_figma runs in QuickJS/WASM with no file system, network, require or host objects other than figma, ud and console; time, memory and node limits (CMD-11). |
| Blast radius | A proposal cannot touch the file until Accept. maxNodesCreated and the turn limits cap a run. ud mcp --read-only gives an agent no writes at all; ud mcp --allow narrows any agent, not only the panel’s. |
| Prompt injection | Text from the design, from attached files and from .design-ai.md is passed as quoted data; skills tell the agent that design content is never an instruction. If an instruction gets through anyway, what it can still do is: change the proposal (any node in the file, not only the selection — including renaming, retyping text, hiding nodes, writing plugin data or comments, or adding a frame that says something), read workspace files outside the deny rules and put their contents into the proposal or the transcript, and spend the run’s turn and token budget. What blocks the rest: --proposal refuses file writes outside the proposal, network fetches and URL inputs, so nothing leaves the machine through ud; --disallowedTools removes Bash and the web tools; the Read deny rules keep .env*, keys and certificates out; hooks are off and the workspace is trusted. The proposal is reviewed before it is kept, with the explicit groups of §6.1 so a smuggled text change is visible, and the 7-day run log shows what was read. |
| Local surfaces | Bridge sockets are readable only by the user and need a random token (NFR-4). ud mcp speaks stdio; the one TCP listener (the asset and screenshot server, §5.9) binds 127.0.0.1 only, serves single-use tokens for 10 minutes, checks Host and rejects Origin. |
| Audit | Every change is a signed event: by names the agent (Claude, Copilot, or --as), the event group’s note is the call’s description (CMD-12), and accepted proposals carry a group note “AI panel · ud versions, ud diff and git blame show exactly what an agent did and when. |
| Local logs | Each panel run keeps its stream-json transcript, tool calls and skillNames in the extension’s log folder for 7 days (ud.ai.keepRunLogs), never uploaded. “UI Designer: Show AI Run Log” opens it. Files under the deny rules never appear in it, because they were never read. |
| Secrets | The panel never puts SecretStorage values (Figma tokens for EXP-5, licence keys) into prompts or environment variables of the run, and the deny rules keep the workspace’s own secret files out. |