Skip to content

Security: elijahshepherd/Coder

Security

docs/SECURITY.md

Coder — Security Architecture

Comprehensive guide to the security model, permission system, data protection, and safety features.


Security Model Overview

Coder implements a defense-in-depth security model with multiple layers:

  1. Permission Engine — Controls what agents can do
  2. Protected Paths — Prevents access to sensitive filesystem locations
  3. Command Filtering — Blocks dangerous system commands
  4. Autonomy Levels — Limits agent freedom based on trust
  5. Sandboxing — Isolates plugin execution
  6. Encrypted Storage — Protects API keys and credentials

Permission Engine

The PermissionEngine is the central security authority. It evaluates every agent action against a rule set and determines whether to allow, deny, or ask the user.

Rule Evaluation Flow

Agent Action
    │
    ▼
Check Cache ──→ Cache Hit ──→ Return Cached Result
    │
    ▼ Cache Miss
Get Autonomy Level
    │
    ▼
Evaluate Rules (priority-ordered)
    │
    ▼
Dangerous Command? ──→ Upgrade to 'ask'
    │
    ▼
Protected Path? ──→ Upgrade to 'deny'
    │
    ▼
Learned Rule? ──→ Apply if confidence >= threshold
    │
    ▼
Return Verdict (allow/deny/ask)

Autonomy Levels

Level Behavior
none Deny everything unless explicitly allowed by a rule
limited Deny by default; upgrade 'ask' verdicts to 'deny'
moderate Default; ask the user for actions without explicit rules
full Allow everything except dangerous commands

Built-in Security Rules

Rule Resource Verdict Priority
Deny /etc/** filesystem deny 100
Deny **/.ssh/** filesystem deny 100
Deny **/.gnupg/** filesystem deny 100
Ask for **/.env filesystem ask 50
Allow registry.npmjs.org network allow 10
Allow pypi.org network allow 10
Ask for npm install* command ask 20
Ask for pip install* command ask 20
Deny format * command deny 200
Deny rm -rf * command deny 200

Dangerous Command Detection

The RuleEvaluator maintains a list of dangerous command patterns:

Blocked Commands

  • rm -rf / rm --recursive --force
  • sudo / runas
  • format (disk formatting)
  • chmod / chown / icacls / takeown
  • dd if= / mkfs.
  • shutdown / reboot / halt / poweroff
  • reg add/delete/import (Windows registry)
  • systemctl stop/disable/mask
  • apt remove / npm uninstall -g / pip uninstall
  • git push --force / git reset --hard / git clean
  • curl | sh / wget | sh (pipe to shell)
  • eval / exec
  • docker rm/rmi
  • kubectl delete

Even at full autonomy, dangerous commands always require explicit user approval.


Protected Paths

The ConfigManager defines OS-specific protected paths:

Linux/macOS

~/.ssh
~/.gnupg
/etc
/usr
/bin
/sbin
/sys
/proc

Windows

%USERPROFILE%\.ssh
%USERPROFILE%\.gnupg
%SystemRoot%\System32
C:\Program Files
C:\Program Files (x86)

The PermissionEngine adds deny rules for all protected paths on initialization.


Learning System

The PermissionStore learns from user decisions to reduce prompt fatigue:

  1. User makes a decision (approve/deny/always/never)
  2. Decision is recorded in the store
  3. After 3+ similar decisions, a learned rule is created
  4. "Always allow/deny" decisions create rules immediately
  5. Learned rules have lower priority than explicit rules

Confidence Thresholds

Threshold Action
>= 85% Auto-apply learned rule
>= 70% Include as lower-priority rule
< 70% Don't auto-apply

API Key Security

API keys are stored using Electron's safeStorage API:

// Encryption
const encrypted = safeStorage.encryptString(apiKey);
fs.writeFileSync(keyPath, encrypted);

// Decryption
const encrypted = fs.readFileSync(keyPath);
const apiKey = safeStorage.decryptString(encrypted);
  • Keys are never stored in plaintext
  • Encryption uses the OS keychain (Keychain on macOS, Credential Manager on Windows, libsecret on Linux)
  • Keys are scoped per-provider

Plugin Sandboxing

Plugins run in a restricted environment:

  • Permission-scoped: Can only access declared permissions
  • Resource-limited: Memory and CPU limits enforced
  • Network-filtered: Only allowed domains accessible
  • Filesystem-scoped: Limited to workspace + plugin directory
  • Error-isolated: Plugin errors don't crash the host

Permission Modes

Mode Description
strict Every action requires approval; autonomy = none
normal Default mode; autonomy = moderate
permissive Most actions allowed; autonomy = full
auto Adjusts based on risk assessment

Audit Trail

All permission evaluations are recorded in the PermissionStore history:

interface PermissionHistoryEntry {
  id: string;
  agentId: string;
  resourceType: string;
  resource: string;
  requested: PermissionVerdict;
  resolved: PermissionVerdict;
  source: 'rule' | 'user' | 'auto' | 'learned';
  durationMs: number;
  timestamp: number;
}

History entries can be queried, filtered, and reviewed through the UI or API.


Best Practices for Contributors

  1. Never hardcode API keys or secrets in source code
  2. Always check permissions before performing agent actions
  3. Use the PermissionEngine instead of direct filesystem/command access
  4. Validate all inputs from external sources (providers, plugins, IPC)
  5. Sanitize file paths to prevent directory traversal
  6. Use parameterized queries for database operations
  7. Log security events for audit purposes
  8. Test permission edge cases in your test suites

There aren't any published security advisories