Security
Copair is a local agent. It runs on your machine, reads your files directly, and spawns subprocesses in your terminal. There is no Copair server, no code upload, and no telemetry. The security model is designed around that reality: your approval is the enforcement point, and secrets never leave your machine in readable form.
Approval gate
Every tool call — file writes, edits, shell commands, git operations — is held at an approval gate before execution. In the default ask mode you see the tool name and its full input, then approve or deny.
Permission modes (permissions.mode in config):
| Mode | Behavior |
|---|---|
ask | Prompt before every tool call (default) |
auto-approve | Approve automatically — use only in trusted, sandboxed environments |
deny | Reject all tool calls; agent can only read and plan |
Allow-list (permissions.allow_tools in config): specific tools can be pre-approved so they never prompt:
permissions:
mode: ask
allow_tools:
- read
- glob
- grepSession-level "always allow" is path-specific for write, edit, read, glob, and grep. Selecting "always" on a write to src/auth.ts approves future writes to that file only — not every write the agent performs. New-file creation always re-prompts even when the file's directory matches an existing allow-list entry. See Permissions & Approval for the full tiered-read behavior.
File system access
Copair enforces a project boundary: the directory where you run copair is the root. By default the agent cannot read or write files outside this root.
Blocked by default (built-in deny list):
~/.ssh/— SSH private keys~/.aws/— AWS credentials~/.gnupg/— GPG keys~/.config/— application credentials~/.netrc,~/.npmrc,~/.pypirc— package registry tokens/etc/— system configuration**/.env,**/.env.*(outside project root)
Expanding access (permissions.allow_paths): grant the agent access to specific paths outside the project root:
permissions:
allow_paths:
- ~/shared-libs
- /data/datasetsOverriding the deny list (permissions.deny_paths): replace the built-in list entirely. When non-empty this list is used instead of the defaults:
permissions:
deny_paths:
- ~/.ssh
- ~/.awsCross-repository bash detection
The bash tool accepts arbitrary shell commands, so the project boundary cannot be enforced by path-checking the tool input. Instead, Copair scans every bash command for path tokens that escape the project root — relative paths starting with ../, absolute paths outside the root, and ~/ home references — and escalates them to a forced approval prompt with a red warning, regardless of the configured permission mode or any matching bash allow-list entry.
⚠ Cross-repository access
bash: cat ../../other-repo/.env
[y]es [n]oThe detection is code-level — a model cannot phrase its way around it by quoting paths differently or piping commands. Workflow YAML files that include shell steps go through the same approval gate before each step executes.
The same tier rules apply to bash as to native file tools: paths inside the project root are allowed without a prompt, sensitive files (.env*, *.pem, id_rsa, etc.) always prompt, and cross-repo paths always prompt.
Secrets handling
API keys and tokens are interpolated from environment variables at config load time — they are never stored in config files. When Copair writes session files, logs, or returns tool output to the model, all text passes through a redaction filter that replaces known secret patterns with [REDACTED:<label>].
Patterns redacted automatically:
- Anthropic API keys (
sk-ant-…) - OpenAI API keys (
sk-…) - GitHub tokens (
ghp_…,github_pat_…) - AWS access keys (
AKIA…) - Linear tokens (
lin_api_…) - Bearer tokens
Redaction runs on: tool output before it is sent to the model, session JSONL entries, and the audit log.
Prompt injection hardening
Copair wraps all file content and tool results in labelled XML context blocks before including them in the model prompt. An anti-injection preamble at the top of the system prompt instructs the model to treat these blocks as data, not instructions.
This limits — but does not eliminate — the risk from adversarial content in files the agent reads. Treat the approval gate as the primary defence: if a tool call looks unexpected, deny it.
MCP server security
When you configure MCP servers, Copair applies several mitigations:
- Env isolation: MCP subprocesses receive a minimal environment (
PATH,HOME,TMPDIR,LANG) by default. No API keys or credentials from the parent shell are forwarded unless you setinherit_env: trueon a specific server. - Startup validation: Copair checks that each configured command exists (
which/existsSync) before starting. Invalid servers are skipped with a warning — startup continues rather than crashing. - Config warnings: If you configure an MCP server with an env key matching a known secret pattern (
_KEY,_SECRET,_TOKEN,_PASSWORD), Copair logs a warning at startup.
mcp_servers:
my-tool:
command: my-mcp-server
args: []
env:
TOOL_CONFIG: /path/to/config # fine
# OPENAI_API_KEY: ... # would trigger a warning
inherit_env: false # default — do not forward parent envConfig reference
| Key | Type | Default | Description |
|---|---|---|---|
security.path_validation | strict | warn | strict | How to handle out-of-boundary path access: strict blocks and returns an error; warn logs and allows |
security.redact_high_entropy | boolean | false | Also redact strings that look like secrets by entropy heuristic, even if they don't match a known pattern |
network.web_search_timeout_ms | number | 15000 | Timeout in ms for web search tool requests |
network.provider_timeout_ms | number | 120000 | Timeout in ms for LLM provider API calls |
permissions.allow_paths | string[] | [] | Paths outside the project root the agent may access |
permissions.deny_paths | string[] | [] | Override the built-in credential deny list. When non-empty, replaces it entirely |
Reporting vulnerabilities
Please report security issues via GitHub Security Advisories. Do not open a public issue for security vulnerabilities.