Security

How Endara is structured to keep a single user's MCP traffic on their own machine. This page describes what listens where, what each listener accepts, and how the desktop and release pipeline are hardened.

Trust model

Endara is a single-user, single-host process. Endara Desktop is the only intended client of the relay's management API (/api/*), and it talks to the relay over a local socket. The MCP plane on TCP loopback exists to serve local MCP clients (Claude Desktop, Cursor, scripts running as the same user). Nothing in Endara is designed to be reachable from another machine, and nothing relies on a shared secret or authentication header for access control — instead, OS-level filesystem and pipe permissions plus a localhost-origin gate keep external callers out.

Network surface

The relay exposes two distinct planes:

MCP plane (TCP loopback)

/mcp, /mcp/*, /healthz, and /oauth/callback are served on 127.0.0.1:9400 (production) or 127.0.0.1:9500 (dev). The router applies a strict localhost-Origin gate — only requests with an Origin header that resolves to a loopback address are accepted. There is no permissive CORS layer on this surface.

Management plane (UDS / Named Pipe)

/api/* is not served on any TCP port. It binds to a per-user local endpoint:

<suffix>is a stable hash of the relay's data-dir, so the dev build (~/.endara-dev) and the installed production build (~/.endara) get distinct sockets and can coexist on the same machine without colliding.

On Unix the relay performs a peer-UID check (SO_PEERCRED / getpeereid) on every accepted connection and rejects callers that don't match the relay's own UID. On Windows the Named Pipe is created with an ACL restricted to the current user's SID. See Management API for the scripting interface.

Why a local socketBecause /api/* does not bind a TCP port, a malicious page running in your browser cannot reach the management API even if it guesses the right URL — there is no http://127.0.0.1:9400/api/... for it to talk to. Local-socket access is gated by filesystem and pipe permissions.

Credential storage

OAuth tokens and client credentials are never written to config.toml. The relay persists them through its TokenManager under ~/.endara/tokens/ with file mode 0600 (owner read/write only). config.toml holds only non-secret connection metadata.

Organization (EMA) credentials

Enterprise-Managed Authorization shares one identity-provider sign-in across an organization's endpoints, so credentials are keyed by organization, not by endpoint. The relay keeps one pooled ID token (plus its refresh token) per organization in the same 0600 credential store, and every EMA endpoint bound to that org draws from it. As with all other credentials, these tokens are never written to config.toml — only the org's name, provider, resolved idp issuer, and optional pre-registered client_id are serialized there. Removing an organization purges its pooled credentials. See Enterprise-Managed Authorization for the configuration model.

Webview CSP

Endara Desktop's Tauri webview ships with a strict default-deny Content-Security-Policy. script-src is restricted to 'self' with no 'unsafe-inline' and no 'unsafe-eval', so a compromised dependency cannot inject inline scripts into the UI. 'unsafe-inline' is permitted only on style-src (CSS-in-JS frameworks need it). The connect-srclist is narrow and explicitly allows the bundled relay's loopback host so legitimate UI traffic still works.

Build & release pipeline

Third-party GitHub Actions on the signing path are pinned by commit SHA, not by tag — Dependabot can still propose updates, but a compromised tag on an upstream action repo cannot silently land in an Endara release. run: blocks funnel any attacker-influenceable input (PR titles, issue bodies, branch names) through env: variables rather than direct shell expansion, eliminating the standard script-injection class of vulnerabilities. The Homebrew tap publish job runs with a least-privilege token scoped to the tap repository only.

Reporting a vulnerability

Please use GitHub's private vulnerability-reporting channel. Both repositories ship a SECURITY.md with the full reporting flow and documented response-time expectations: acknowledgement within 3 business days and a status update within 7 business days.

For deeper background on the threat model the relay was designed against, see the relay's THREAT_MODEL.md.