Skip to main content

Principle of Least Privilege

OpenPact implements the principle of least privilege throughout its architecture. Every component receives only the minimum permissions necessary to perform its function.

What Is Least Privilege?

The principle of least privilege (PoLP) states that every component, user, or process should have only the access rights necessary to perform its legitimate purpose. This limits the damage that can result from accidents, errors, or unauthorized use.

Two-Layer Security Model

OpenPact enforces least privilege through two independent layers:

Layer 1: Linux User Separation

The AI process (opencode serve) runs as openpact-ai, a restricted Linux user, while the orchestrator runs as openpact-system. File permissions enforce boundaries:

PathOwnerModeAI Access
/workspace/openpact-system:openpact750Group-read/execute (can traverse)
/workspace/secure/openpact-system:openpact700Denied (owner-only)
/workspace/secure/config.yamlopenpact-system:openpact600Denied (owner-only)
/workspace/secure/data/openpact-system:openpact700Denied (owner-only)
/workspace/ai-data/openpact-system:openpact750Group-read/execute (MCP tools scope here)
/workspace/ai-data/memory/openpact-system:openpact770Group-read/write
/workspace/ai-data/scripts/openpact-system:openpact750Group-read
/workspace/ai-data/skills/openpact-system:openpact750Group-read
/workspace/ai-data/SOUL.mdopenpact-system:openpact640Group-read
/workspace/ai-data/USER.mdopenpact-system:openpact640Group-read
/workspace/ai-data/MEMORY.mdopenpact-system:openpact660Group-read/write

Layer 2: Application Tool Restriction

OpenCode's built-in tools (bash, write, edit, read, grep, glob, list, patch, webfetch, websearch) are all disabled via the OPENCODE_CONFIG_CONTENT environment variable. The AI can only use explicitly registered MCP tools provided by OpenPact's standalone MCP server.

AI Access Restrictions

What the AI Can Access

ResourceAccess LevelHow
MCP toolsDefined set onlyRegistered tools via MCP server
Script executionApproved onlyscript_run MCP tool (requires admin approval)
Workspace filesRead via MCPworkspace_read, workspace_list tools
Memory systemRead/write via MCPmemory_read, memory_write tools
Web contentFetch via MCPweb_fetch tool
CalendarRead via MCPcalendar_read tool
Chat providersSend via MCPchat_send tool

What the AI Cannot Access

  • Shell commands -- OpenCode's bash tool is disabled
  • Direct file writes -- OpenCode's write/edit/patch tools are disabled
  • Environment variables -- only LLM provider keys and system basics are passed through
  • Sensitive tokens -- DISCORD_TOKEN, GITHUB_TOKEN, SLACK_BOT_TOKEN, ADMIN_JWT_SECRET excluded
  • Secure directory -- secure/ has owner-only permissions (700), blocking group access to config and data
  • Config file -- inside secure/, owner-only permissions (600)
  • Secret values -- scripts see secrets but output is redacted with [REDACTED]
  • Unapproved scripts -- script_run checks approval status
  • Admin UI operations -- admin API requires JWT auth

Environment Variable Isolation

The AI process receives a filtered environment. Only these variables pass through:

System basics: PATH, HOME, USER, LANG, TERM, TZ, TMPDIR, XDG_*

LLM provider keys: ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY, AZURE_OPENAI_API_KEY, OLLAMA_HOST

Explicitly excluded: DISCORD_TOKEN, GITHUB_TOKEN, SLACK_BOT_TOKEN, TELEGRAM_BOT_TOKEN, ADMIN_JWT_SECRET, all Starlark secrets, and any other environment variable not in the allowlist.

In Docker, the entrypoint sets HOME and USER to the AI user's home directory when launching OpenCode as openpact-ai.

MCP Tool Boundaries

Each MCP tool has explicit capability boundaries:

File Tools

ToolCapabilitiesRestrictions
workspace_readRead workspace filesai-data/ directory only, path validation
workspace_writeWrite workspace filesai-data/ directory only, path validation
workspace_listList workspace contentsai-data/ directory only

Memory Tools

ToolCapabilitiesRestrictions
memory_readRead MEMORY.md, SOUL.md, USER.md, daily filesValidated paths only
memory_writeWrite memory/context filesValidated paths only, triggers context reload

Script Tools

ToolCapabilitiesRestrictions
script_runExecute approved scriptsAdmin approval required, sandboxed
script_execExecute inline StarlarkSandboxed, no filesystem access
script_listView script metadataIncludes approval status
script_reloadReload scripts from diskAdmin must place files

Communication Tools

ToolCapabilitiesRestrictions
chat_sendSend messages via providersProvider must be active
web_fetchFetch HTTP/HTTPS URLsRead-only, size limits
calendar_readRead calendar eventsConfigured feeds only

Configuration

Enabling User Separation

In Docker, user separation is automatic. The entrypoint launches OpenCode as openpact-ai and the orchestrator as openpact-system — no configuration needed.

The MCP server binary is auto-discovered at startup (next to the main binary, or via PATH). No configuration is needed.

Dev Mode vs Production

SettingDev ModeProduction (Docker)
User separationNone (single user)Entrypoint runs OpenCode as openpact-ai
MCP serverAuto-discovered from PATHAuto-discovered at /app/mcp-server
Built-in toolsDisabled (config still applied)Disabled
File permissionsHost OS permissionsEntrypoint sets strict permissions

Monitoring Least Privilege

Audit Questions

Periodically review:

  • Which scripts have access to which secrets?
  • Are all approved scripts still needed?
  • Are there unused secrets that should be removed?
  • Is the workspace directory appropriately scoped?

Verification

# Verify AI process runs as correct user
docker exec <container> ps aux | grep opencode
# Should show openpact-ai, not openpact-system

# Verify file permissions
docker exec <container> ls -la /workspace/
docker exec <container> ls -la /workspace/ai-data/

Summary

ComponentLeast Privilege Implementation
AI processRuns as openpact-ai, filtered env, disabled built-in tools
MCP toolsExplicit registration, path validation, approval workflow
ScriptsStarlark sandbox, admin approval, secret redaction
WorkspaceAI scoped to ai-data/ only, group-based permissions
SecretsOwner-only secure/data/ dir, env filtering, output redaction
ContainerNon-root users, entrypoint permissions, Docker isolation