Trust boundaries
Security
What we try to protect, where the walls are, and how to report a hole. The privacy page is the one that says what data leaves the browser. This page is about who can reach what after that.
Threat model
Aperture is an editor that runs agent-written code and talks to model providers with your keys. The main risks we design against:
- Agent-written code escaping the tab. Parse, import, and type checks, the page preview, and npm run test in the built-in runner run in the browser. The test runner is a Worker inside a sandbox="allow-scripts" frame with an opaque origin and a CSP that blocks the network. That code must not reach Aperture's API, the page's storage, or the open internet.
- Your keys and tokens leaving the place they belong. Provider keys, custom endpoint keys, GitHub tokens, and MCP tokens are encrypted with AES-256-GCM on the account. The browser only sees the last four characters. On a send, the server decrypts the key you chose and calls that provider. There is no shared Grok key on the hosted demo.
- Secrets in the project being sent to a model. .env (not .env.example), private keys, and credential files are dropped before a send. Lines that look like API keys, tokens, or passwords are replaced with [redacted].
- A verify sandbox reading this app's secrets. When a project is run in a server-side sandbox, it only gets a closed environment (CI, NODE_ENV=test, npm flags) — never this app's database URL, session secrets, or provider keys. Network is limited to package registries.
- Account and session abuse. Sign-in holds the saved project and encrypted keys. Sessions can be ended by signing out. See the privacy page for what is stored on the account.
Honest limits
- Not pure browser-only after sign-in. Once you sign in, the project is saved to your account as you edit. Each Composer, Chat, Inline, or Tab send uploads a snapshot to Aperture's server. The server uses that snapshot to run tools, then forwards the prompt to the provider you picked (unless the host is in replay mode). Localhost Ollama / LM Studio is the exception: that turn stays on your machine.
- Browser sandbox walls are browser walls. Opaque origin + CSP is as far as a tab can go. A browser bug, a mis-set sandbox attribute, or a future runner change could weaken that. Reports that show a path out of the runner are especially welcome.
- Server-side sandbox network is allowlisted, not air-gapped. Package installs need registry access (registry.npmjs.org, related hosts, codeload.github.com). That narrows exfiltration; it is not a claim that untrusted code is safe to run.
- A green check is not a security review. Checks catch parse, import, type, preview, and test failures on staged edits. They do not prove the change is safe to ship or free of vulnerabilities in your app.
- You choose what to open and send. Opening a repo or folder you are not allowed to send to a provider is still your responsibility. The model sees the prompt for that turn under that provider's terms.
Sandbox limits (summary)
| Surface | Boundary |
|---|---|
| In-tab tests | Worker in sandboxed frame, opaque origin, CSP blocks network. ~10s budget. |
| Preview / render check | Script-sandboxed frame with an opaque origin. |
| Server verify run | Declared package.json scripts only (no dev/start/watch). Closed env. Registry allowlist. Time cap. |
Vulnerability disclosure
Please do not report security problems in public issues.
Report them privately through GitHub: open the repository's Security → Report a vulnerability form. Include what an attacker could do, the steps to reproduce it, and the version or commit you tested. You'll get an answer within a week.
The same policy lives in SECURITY.md. Areas where a report is especially welcome: the in-browser test runner (src/lib/runner/), preview and render-check frames, the agent's run allowance and sandbox env (src/lib/sandbox/policy.ts), and sign-in / session handling.
Questions about data handling go to the privacy page. How often checks stop a bad edit is on the checks benchmark.