PairAdminGet it

Security

Threat model

This document states, precisely and verifiably, what PairAdmin sends to a model, what it never sends, what runs locally, and where the boundaries are. Every claim cites the code that makes it true; where a claim is a hard architectural guarantee, the verification command is printed so you can check it yourself.

01 · What PairAdmin sends, exactly

A request to a model contains three things and nothing else: the system prompt, the last N lines of the terminal you are looking at, and what you typed. No conversation history, no other tabs, no filesystem, no saved connections.

services/llm/context.go — BuildMessages() returns exactly []Message{system, user}.

02 · What it never sends

  • Conversation history — for any tab.
  • Other sessions or tabs.
  • Your filesystem.
  • Saved connection details or credentials.
  • Terminal content before you press send — read only inside handleSend.

03 · What runs locally

  • Credential redaction — in-process, before the provider call.
  • The audit log — a local rotating JSONL file.
  • Key storage — the OS keychain or an encrypted file, plus memguard enclaves in memory.
  • Local inference — Ollama and LM Studio default to loopback.

04 · The execution boundary

The assistant has no path to the shell. There is no tool-calling, function-calling, or agent-loop code anywhere in the tree — not a disabled permission, an absence. Verify it yourself:

git grep -niE '"tools"|tool_choice|function_call|tool_use|ToolCall' origin/master -- services frontend/src

This returns zero. The only writes into a terminal are sendToTerminal(), called from button click handlers, and your own typing.

05 · Redaction pattern list

Fifteen patterns, scrubbed in-process before transmission, plus any regexes you add with /filter:

aws-access-key-idgithub-tokengitlab-personal-access-tokenopenai-api-keyanthropic-api-keyslack-tokengoogle-api-keygoogle-service-accountazure-account-keybearer-tokenjwtpem-private-keypassword-assignmentgeneric-api-keyconnection-string-credentials

06 · Audit log contents

Every prompt and every response is written to a local rotating JSONL log. It records the operator's typed message and the model's reply, plus statistics about the transmitted terminal context — line count, byte count, and which redaction patterns matched, with match counts. The terminal context content itself is never logged.

07 · Key storage

API keys and the file-backend master password are held in the OS keychain (macOS Keychain / Windows Credential Manager / Secret Service) or an encrypted file backend, and in memguard enclaves while in memory (ADR-0003).

08 · SSH host-key pinning

Remote SSH sessions use trust-on-first-use host-key pinning with a per-user trust store (ADR-0002). No blanket skip-verify.

09 · Known limitations

  • The audit log records statistics about the transmitted terminal context (line/byte counts and per-pattern redaction matches), but never the content itself.
  • Redaction is regex-based; it is not a commercial secret-scanning engine.
  • Remote Ollama is supported by design (defaults to loopback; Settings warns while a non-loopback host is configured).
  • There is no central or fleet lockdown in the open build — the posture is set per operator.
  • On Linux, the WebKit content-process sandbox is disabled (ADR-0001: the sandbox's bubblewrap/user-namespace requirement can fall back to a blank window, so it is disabled; only bundled, trusted UI assets load).

10 · How to run fully air-gapped

Set the provider to Disable Pair LLM — no model is constructed and no endpoint is contacted, and the status bar reads Disabled (amber) for the whole session. Or point PairAdmin at a local Ollama or LM Studio on loopback. The app has no account and no telemetry; nothing phones home.