Files
agents/SECURITY.md
T
Felix FaerberandClaude Opus 4.8 06df6320a1 security: isolate agent behavior from the caller repo
The agent runs inside the CALLER repo's checkout and opencode auto-discovers project-level config
from the working tree (opencode.json / .opencode/ for provider/model/permission/mcp/plugins, and
AGENTS.md/CLAUDE.md for instructions). opencode has no flag to disable that discovery, so any caller
repo could swap the model, unlock skills/permissions, register MCP servers or plugins (arbitrary
code execution on the runner, which holds ANTHROPIC_API_KEY/AGENT_TOKEN/TOKEN_*/SSH_PRIV_KEY), or
rewrite the rules the agent follows. The trigger gate only restricts who triggers, not what repo
content defines behavior.

- run-agent.sh: quarantine caller-controlled opencode.json/opencode.jsonc/.opencode/AGENTS.md/CLAUDE.md
  for the duration of each run (moved aside, restored on EXIT via trap). Restore keeps the committed
  tree/PR diff unchanged even when the agent commits mid-run.
- run-agent.sh: dev-agent golden rules now come from scripts/agent-rules.md (platform-authoritative),
  injected into the prompt, instead of "read the caller's AGENTS.md and follow it exactly".
- scripts/agent-rules.md: new repo-agnostic authoritative rules.
- SECURITY.md: documents the isolation model and the requirement that callers pin agent.yml@main.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 11:05:46 +03:00

1.8 KiB

Security model — agent behavior isolation

Agent behavior — which models run, what skills / permissions / MCP servers they get, and the golden rules they follow — is defined only by this agents repository. A caller repository must not be able to change it.

For caller repos

Call the shared workflow pinned to this repo's main:

uses: ffaerber/agents/.gitea/workflows/agent.yml@main
secrets: inherit

Do not point uses: at a fork or a non-main ref. The trigger gate, the agent registry, and the isolation controls all live here on main; a caller that repoints it opts out of these protections.

How isolation is enforced at runtime

The agent runs inside the caller repo's checkout, and opencode auto-discovers project-level config from the working tree. Because opencode has no flag to disable that discovery, the run (scripts/run-agent.sh) quarantines the caller-controlled behavior files for the duration of each run so they cannot override the agent's configuration or execute code on the runner (which holds the workflow secrets):

  • opencode.json / opencode.jsonc — provider, model, permission, mcp
  • .opencode/ — plugins, skills, agents, commands, tools
  • AGENTS.md / CLAUDE.md — instructions

They are moved aside before opencode starts and restored after it exits, so the committed tree is unchanged. The authoritative configuration comes from ~/.config/opencode/ (written by scripts/install-opencode.sh), and the authoritative golden rules from scripts/agent-rules.md, injected into the agent prompt. A caller repo's own AGENTS.md is informational to humans only and is never followed as rules by the agent.

Consequence: an agent cannot durably edit these quarantined files during a run — its changes to them are not persisted. Change them via a normal human PR instead.