Security

Local-first architecture, stdio-only MCP, and why Working Mind is safer than cloud agents.

Local-First Is an Attack Surface Decision

Working Mind runs entirely on your machine. No cloud backend. No data relay. No hosted model. Every byte of your data stays on your disk, and every network request goes directly from your machine to the LLM provider you chose.

This isn't a privacy feature tacked on after the fact. The entire architecture is built around the principle that the safest data is data that never leaves your machine.

What Working Mind Never Does

  • Never opens a listening port. The application is a terminal client, not a server. There is no HTTP server, no WebSocket, no REST API exposed to the network.
  • Never sends your data to a third party. The only outbound network traffic is to your configured LLM provider (OpenAI, Anthropic, Google, OpenRouter). Working Mind does not phone home, collect telemetry, or report usage.
  • Never stores credentials in the cloud. API keys live as environment variables on your machine. No keychain, no credential manager, no remote vault.
  • Never runs code you didn't approve. Tool calls require explicit confirmation by default. The agent cannot execute arbitrary commands without your consent.

The MCP Security Model

Working Mind connects to MCP (Model Context Protocol) servers using stdio transport only. This is a deliberate choice with specific security implications:

Stdio vs. SSE/HTTP

AspectStdio (Working Mind)SSE/HTTP (Other tools)
Network exposureNone -- local process onlyOpen port, accessible to other processes
Attack surfaceProcess boundary onlyHTTP server with request parsing
AuthenticationOS process isolationMust implement auth layer
Known CVEs050+ across MCP implementations

The MCP protocol specification supports multiple transport layers. Working Mind exclusively uses stdio, which means each MCP server runs as a child process communicating through stdin/stdout pipes. No network socket is ever created.

MCP Child Process Isolation

Each MCP server runs as an isolated child process:

  1. Environment variables are filtered. The child process receives only the environment variables declared in the pack's pack.json. Your full process.env is not inherited.
  2. The process cannot dial out beyond what its own code does (e.g., the brave-search server makes HTTPS requests to the Brave API). There is no general-purpose network proxy.
  3. The process terminates when Working Mind terminates. No daemon mode, no background service, no zombie processes.

Confirmation Gates

By default, every tool call from the agent requires your approval:

[Tool Call] memory_create_entities
  entities: [{ name: "Project Alpha", observations: [...] }]
  
  Approve? [Enter = yes, type reason = no]

This prevents the agent from silently making changes to your knowledge graph, searching the web, or scraping URLs without your knowledge.

MCP tools currently bypass this gate (they are considered non-destructive). Future releases will add per-tool destructive flags so you can control which MCP tools require confirmation.

Knowledge Graph Integrity

Your knowledge graph is stored as a SQLite database on disk (~/.wmind/memory.sqlite by default). This means:

  • You can read it with any SQLite tool. No proprietary format, no database lock-in. sqlite3 ~/.wmind/memory.sqlite to inspect.
  • You can back it up with cp. One file, one copy command.
  • You can delete it with rm. No orphaned data in a remote database you forgot about.
  • Corruption recovery is automatic. On every open, PRAGMA integrity_check runs. If the database is corrupt, it is renamed and a fresh one is created.

Current Limitations

Alpha Release. The knowledge graph has no access control, no audit log, and no version history. A tool call can overwrite or delete entities without undo. Contradiction detection is pattern-based and covers common cases (preference, state, scalar, location), but does not use LLM reasoning. These safeguards will be improved in future releases.

Data Flow Diagram

Your Terminal
    |
    | stdin/stdout (pipes, no network)
    |
Working Mind (agent loop)
    |
    |--- HTTPS ---> LLM Provider (OpenAI, Anthropic, Google, OpenRouter)
    |
    |--- stdin/stdout (pipes, no network)
    |
    MCP Server (e.g., brave-search, firecrawl)
         |
         |--- HTTPS ---> External API (Brave, Firecrawl, etc.)

Notice: there are exactly two kinds of network traffic, and both are direct HTTPS connections initiated by code running on your machine. No proxy, no relay, no middleware.

Threat Model

ThreatMitigationStatus
LLM provider data breachData never stored by Working Mind; prompt content is between you and your providerMitigated
MCP server code injectionStdio-only; filtered env vars; no network listenerMitigated
Agent executes destructive tool callConfirmation gates on all non-MCP toolsPartial (MCP tools bypass gate)
Malicious pack system promptUser explicitly loads packs; prompt visible in TUIMitigated
Credential theft from diskKeys in env vars, not persisted files; filtered from child processesMitigated
Supply chain attack on MCP packagesUser installs and configures MCP servers explicitlyAccepted risk
Knowledge graph corruptionSQLite with integrity check on open; corrupt files auto-backed-up and recreatedMitigated (no undo)
Session history exposureRaw JSON on disk; user controls file permissionsAccepted risk

Reporting Security Issues

If you find a security vulnerability, please report it privately to security@elgap.dev before filing a public issue. We will respond within 48 hours and work with you on responsible disclosure.