Fully hiding the caller's AGENTS.md dropped repo-specific operational knowledge agents need (e.g. homelab's migration mechanism: deleting a service requires a matching migrations/*.sh, else the old service keeps running in prod). Separate the two concerns: - Platform golden rules stay authoritative (scripts/agent-rules.md), un-overridable. - The caller's AGENTS.md / CLAUDE.md text is captured before quarantine and injected into the prompt as explicitly SUBORDINATE context — usable for repo mechanics, but unable to change behavior, grant permissions, or override the rules. - opencode.json / .opencode remain fully blocked (config + RCE), never re-injected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2.3 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, toolsAGENTS.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.
opencode.json / .opencode/ are fully blocked — never re-introduced — because they can change
config or execute code.
AGENTS.md / CLAUDE.md are treated as repo notes, not rules. A caller repo legitimately uses
its AGENTS.md to document repo-specific mechanics (build/deploy/migration conventions) the agent
needs. So its text is captured and injected into the prompt as explicitly subordinate context —
useful for how the repo works, but unable to change agent behavior, grant permissions, or override
the golden rules. It is never auto-loaded by opencode as top-level instructions.
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.