Skip to content
Pilotoo
v0.1

Security

Any local process and any web page can reach a localhost port. The local backend therefore refuses by default and asks you to write down two decisions: how the agent executes, and which pages may talk to it. Every request also needs a per-launch token.

await startLocalServer({
// ...
execution: 'local-unsandboxed',
});

execution: 'local-unsandboxed' runs the agent’s execute tool as a shell on this machine, with the current user’s permissions and environment. The package will not start without the choice written down, so nobody gets it by omission. A sandboxed backend is a later phase.

@pilotoo/agent-runtime takes the same choice (createAgentBackend(..., { execution })) and throws on a value it cannot serve instead of falling back to the shell. The shared gateway, which leaves it out, is unchanged.

allowedOrigins is required. The desktop launcher passes the webview origins, plus the dev server’s origins in development.

await startLocalServer({
// ...
allowedOrigins: ['tauri://localhost'],
});

A request with an Origin outside the list is refused (403 on REST, no socket), token or not. An empty list refuses every request that carries one. A request with no Origin is judged by the token alone.

Page Origin it sends
Tauri webview on macOS or Linux tauri://localhost
Tauri webview on Windows http://tauri.localhost or https://tauri.localhost
A dev server its own origin

Every request needs Authorization: Bearer <token>:

  • REST goes through the identity guard and answers 401 without it.
  • Sockets go through the same resolver in the handshake and fail with connect_error UNIDENTIFIED.

Both sides are hashed and compared in constant time. The caller is the fixed local identity: subject: local, tenant: local, roles: [owner]. /health and /protocol stay open, though they are still origin-checked.

The client needs nothing special: pass the base URL and credentials: () => token to chat-core (see Connecting a client).