7  Security

7.1 Project Trust

Project trust controls whether Pi loads project-local settings, resources, packages, and extensions. It is not a sandbox and it does not restrict what the model can ask tools to do after you start working in a directory.

7.1.1 What Requires Trust

Pi considers a project to have resources that require trust when it finds any of these from the current working directory:

  • .pi/settings.json
  • .pi/extensions, .pi/skills, .pi/prompts, or .pi/themes
  • .pi/SYSTEM.md or .pi/APPEND_SYSTEM.md
  • Project .agents/skills in the current directory or an ancestor directory

A bare .pi directory does not count as a project resource that requires trust.

7.1.2 Trust Mechanism

When an interactive session starts in a project with resources that require trust and no saved decision exists, Pi follows defaultProjectTrust from global settings. The default value is "ask", which prompts the user.

Saved decisions are stored by canonical directory in ~/.pi/agent/trust.json. The closest saved decision on the current or parent path applies before the global default.

Trusting a project allows Pi to load:

  • .pi/settings.json
  • Pi resources (extensions, skills, prompt templates, themes, system prompt files)
  • Missing project packages configured through project settings
  • Project-local extensions and project package-managed extensions
Note

Before trust is resolved, Pi only loads context files, user/global extensions, and CLI -e extensions. User/global extensions can handle the project_trust event; the first extension that returns a yes/no decision owns the decision.

7.1.3 Non-Interactive Modes

Non-interactive modes (-p, --mode json, --mode rpc) do not show a trust prompt. Without a saved trust decision:

  • "ask" (default) and "never" ignore project resources
  • "always" trusts them

Pass --approve/-a or --no-approve/-na to override project trust for one run.

7.1.4 Managing Trust

Use /trust in interactive mode to save a project trust decision for future sessions, including trust for the immediate parent folder. It writes ~/.pi/agent/trust.json only; the current session is not reloaded, so restart Pi for changes to take effect.

Configure defaultProjectTrust in ~/.pi/agent/settings.json:

{
  "defaultProjectTrust": "ask"  // "ask", "always", or "never"
}

7.2 No Built-in Sandbox

Pi does not include a built-in sandbox. This is an intentional design decision.

Built-in tools can read files, write files, edit files, and run shell commands with the permissions of the Pi process. Extensions are TypeScript modules that run with the same permissions. Package installs, shell commands, language servers, test commands, and other developer tools behave as ordinary local processes.

Warning

A partial in-process sandbox would be easy to misunderstand as a security boundary while still depending on the host shell, filesystem, package managers, credentials, and extension code. Real isolation needs to come from the operating system or a virtualization/container boundary.

7.2.1 Why Not a Partial Sandbox?

Pi is designed to operate on local source trees, invoke project toolchains, and integrate with the user’s existing development environment. Key reasons for not including a sandbox:

  1. False sense of security: A partial sandbox would still depend on host systems
  2. Complexity: Maintaining sandbox boundaries for every tool path adds significant complexity
  3. Breaks workflows: Sandboxes interfere with legitimate development tool access
  4. Already solved: Operating systems and containers provide proven isolation

7.2.2 Project Trust vs. Sandbox

Project trust is only an input-loading guard. It prevents a repository from silently changing Pi’s settings or extensions before you approve it. It does not make untrusted code, untrusted prompts, or untrusted model output safe.

Prompt injection from repository files, comments, documentation, context files, or build output is expected local-agent risk and cannot be reliably prevented by Pi.

7.3 Running Untrusted Work

For untrusted repositories, generated code you do not intend to monitor closely, or unattended automation, run Pi in a contained environment.

7.3.1 Best Practices

  1. Use a container, VM, micro-VM, remote sandbox, or policy-controlled sandbox with only the files and credentials required for the task
  2. Run the whole Pi process inside a container/sandbox (see Containerization)
  3. Run host Pi while routing built-in tool execution into a Gondolin micro-VM
  4. Mount only the workspace paths the agent should access
  5. Avoid mounting host ~/.pi/agent unless the container should access host sessions, settings, and credentials
  6. Pass the minimum required API keys or use short-lived credentials
  7. Restrict network access when the task does not need it
  8. Review diffs and outputs before copying results back to trusted systems
Tip

If you bind-mount a host workspace read/write, writes from inside the container or VM can still modify host files. Use read-only mounts or copy files into and out of the sandbox when you need stronger protection from unintended writes.

7.3.2 Containerization Patterns

Three common patterns are documented in the Containerization chapter:

Pattern What Is Isolated Best For
Gondolin Built-in tools and ! commands Local micro-VM with host auth
Plain Docker Whole Pi process Simple local isolation
OpenShell Whole Pi process in policy-controlled sandbox Local or remote managed sandbox

7.4 Reporting Security Issues

To report a security issue, follow the repository Security Policy. Do not open a public issue for security-sensitive reports.

7.4.1 What Is Not a Security Issue

The following are generally outside the security boundary unless the report demonstrates a real privilege-boundary bypass:

  • Expected local-agent behavior
  • Lack of a built-in sandbox
  • Prompt injection from untrusted content
  • Behavior of user-installed extensions or skills

A valid security report should show how Pi grants access that the local user did not already have.

Warning

Do not open public GitHub issues for security-sensitive reports. Use the repository’s Security Policy to report vulnerabilities responsibly.

7.5 Extension Security

Extensions run with your full system permissions and can execute arbitrary code. This means:

  • An extension can read, write, or delete any file accessible to your user account
  • An extension can execute arbitrary shell commands
  • An extension can make network requests to any endpoint
  • An extension can access environment variables, credentials, and auth files

7.5.1 Evaluating Extensions

Before installing an extension, consider:

  1. Source reputation — Is the extension from a trusted author or organization?
  2. Code review — Can you read and understand the extension’s source code?
  3. Dependencies — What npm packages does the extension depend on? Are they trustworthy?
  4. Permissions scope — Does the extension request more access than it needs?
  5. Maintenance — Is the extension actively maintained and updated?

7.5.2 Extension Sources

Source Trust Level Recommendation
Official Pi examples High Safe to use
Your own extensions High You control the code
Extensions from known authors Medium Review before installing
Extensions from npm Medium Check package and author reputation
Extensions from unknown sources Low Do not install without code review
Warning

Never install extensions from untrusted sources without reviewing the source code. Extensions have full access to your system.

7.6 Credential Safety

Pi stores credentials in ~/.pi/agent/auth.json with 0600 permissions (user read/write only). Despite this, there are scenarios where credentials can be exposed:

7.6.1 Risks

  1. Model output — The model could inadvertently print API keys or tokens in its responses
  2. Tool output — Shell commands that print environment variables or read config files
  3. Session files — Sessions contain full conversation history, including any secrets that were discussed
  4. Extension code — Malicious extensions could exfiltrate credentials
  5. Shared sessions — Exported or shared sessions may contain sensitive information

7.6.2 Best Practices

  • Use key resolution — Store keys via !command (e.g., from a password manager) instead of literals
  • Minimize stored credentials — Only configure providers you actively use
  • Review sessions before sharing — Check /export output for sensitive data
  • Use short-lived credentials — When available, prefer tokens that expire
  • Restrict extension access — Do not install extensions that handle credentials unless necessary

7.6.3 Key Resolution Best Practices

//  Good: Key retrieved from password manager
{
  "type": "api_key",
  "key": "!op read 'op://vault/anthropic/credential'"
}

//  Good: Key from environment variable
{
  "type": "api_key",
  "key": "$ANTHROPIC_API_KEY"
}

// ⚠️ Caution: Literal key stored in file
{
  "type": "api_key",
  "key": "sk-ant-1234567890..."
}

7.7 Network Security

Pi makes outbound network requests to:

  • LLM provider APIs (Anthropic, OpenAI, Google, etc.)
  • Package registries (npm) during pi install and pi update
  • Git repositories during pi install git:...
  • OAuth callbacks during /login flows

7.7.1 Restricting Network Access

For environments that require network restrictions:

  1. Use a proxy — Configure proxy in settings to route through an HTTP proxy
  2. Firewall rules — Restrict outbound traffic to known API endpoints
  3. Container networking — Use Docker network policies or OpenShell network rules
  4. VPN — Route Pi traffic through a corporate VPN
// Settings: route through corporate proxy
{
  "proxy": "http://corporate-proxy.internal:8080"
}

7.8 Security Checklist

Before using Pi in a new environment: