fix: opencode config 2

This commit is contained in:
2026-07-21 00:42:56 +02:00
parent 6b857e9adb
commit 7a1b18f931
3 changed files with 21 additions and 33 deletions
+16 -15
View File
@@ -69,13 +69,14 @@ to `^1`. The build verifies that the resolved version is still OpenCode 1.x and
requests a no-cache build so the configured range is resolved again on each build. Runtime requests a no-cache build so the configured range is resolved again on each build. Runtime
auto-update is disabled so an image cannot cross into OpenCode 2.x after it is built. auto-update is disabled so an image cannot cross into OpenCode 2.x after it is built.
The trusted configuration is `opencode/opencode.json`. It grants `permission: "allow"` globally The trusted configuration is `opencode/opencode.json`. OpenCode's default global and built-in-agent
and to every built-in or custom agent that Agent CI can invoke. Repository-local OpenCode config permission policies remain in effect; Agent CI does not replace them with an allow-all policy.
and external plugins are disabled so a clone cannot replace the service policy. OpenCode's default Repository-local OpenCode config and external plugins are disabled so a clone cannot replace the
plugins remain enabled for provider authentication. Its scanned home and global configuration paths service policy. OpenCode's default plugins remain enabled for provider authentication. Its scanned
are root-owned and read-only, and external skill discovery is disabled, so an agent cannot persist home and global configuration paths are root-owned and read-only, and external skill discovery is
instructions for later repositories. CodeGraph, Context7, and `gh_grep` are configured as MCP disabled, so an agent cannot persist instructions for later repositories. CodeGraph, Context7, and
servers. Set `AGENTCI_CONTEXT7_API_KEY` to raise Context7 rate limits. `gh_grep` are configured as MCP servers. Set `AGENTCI_CONTEXT7_API_KEY` to raise Context7 rate
limits.
The `research` subagent can only use Exa web search, Context7, and the `gh_grep` public-code search The `research` subagent can only use Exa web search, Context7, and the `gh_grep` public-code search
MCP. All filesystem, shell, editing, task, and other tools are denied for that agent. Exa is enabled MCP. All filesystem, shell, editing, task, and other tools are denied for that agent. Exa is enabled
@@ -84,11 +85,10 @@ and locally excludes `.codegraph/` from Git.
### Security boundary ### Security boundary
OpenCode does not provide an OS sandbox. It can execute shell commands, edit Git metadata and OpenCode does not provide an OS sandbox. Its default permission system controls agent tools and
environment files, access external directories, use loopback and network services, bind ports, and approval requests, while Docker limits what the non-root process can reach. Any shell command that
invoke subagents without approval. It can access every shared workspace, development tool, runtime OpenCode permits still has the Unix-level access of that container user, so environment filtering
credential, and mounted file readable by the non-root container user. Environment filtering is is only accidental-exposure hygiene and cannot protect readable files from an allowed shell command.
only accidental-exposure hygiene and cannot protect readable files from shell commands.
Docker remains the OS boundary. The services run as non-root without added capabilities, Docker remains the OS boundary. The services run as non-root without added capabilities,
privileged mode, an unconfined seccomp/AppArmor profile, or a nested `bubblewrap` sandbox. The only privileged mode, an unconfined seccomp/AppArmor profile, or a nested `bubblewrap` sandbox. The only
@@ -113,11 +113,12 @@ Every name resolves to a file in `install-scripts/`, mounted read-only at
run after each implementation clone or branch sync and fail the job on an unknown script, timeout, run after each implementation clone or branch sync and fail the job on an unknown script, timeout,
or non-zero exit. They receive no Agent CI or Gitea secret values in their environment, but remain or non-zero exit. They receive no Agent CI or Gitea secret values in their environment, but remain
trusted operator code. Tools persist under `/var/lib/agentci/dev-tools`, and OpenCode can read or trusted operator code. Tools persist under `/var/lib/agentci/dev-tools`, and OpenCode can read or
modify them through its unrestricted shell. See `install-scripts/README.md` for the script contract. modify them through shell commands permitted by its active agent policy. See
`install-scripts/README.md` for the script contract.
Agent CI continues to create branches, validate diffs, commit, and push after OpenCode returns. This Agent CI continues to create branches, validate diffs, commit, and push after OpenCode returns. This
keeps workflow behavior deterministic, but unrestricted OpenCode is not prevented from running Git keeps workflow behavior deterministic, but an OpenCode agent with shell permission can still run
commands itself. Git commands itself.
## State and recovery ## State and recovery
+1 -12
View File
@@ -4,21 +4,10 @@
"share": "disabled", "share": "disabled",
"subagent_depth": 1, "subagent_depth": 1,
"instructions": ["/etc/opencode/AGENTS.md"], "instructions": ["/etc/opencode/AGENTS.md"],
"permission": "allow",
"agent": { "agent": {
"build": {
"permission": "allow"
},
"plan": {
"permission": "allow"
},
"general": {
"permission": "allow"
},
"explore": { "explore": {
"model": "{env:AGENTCI_EXPLORE_MODEL}", "model": "{env:AGENTCI_EXPLORE_MODEL}",
"variant": "{env:AGENTCI_EXPLORE_VARIANT}", "variant": "{env:AGENTCI_EXPLORE_VARIANT}"
"permission": "allow"
}, },
"research": { "research": {
"description": "Research current documentation, web evidence, and public code examples.", "description": "Research current documentation, web evidence, and public code examples.",
+4 -6
View File
@@ -2,15 +2,13 @@ import json
from pathlib import Path from pathlib import Path
def test_config_grants_parent_agents_access_and_restricts_research() -> None: def test_config_preserves_builtin_permissions_and_restricts_research() -> None:
root = Path(__file__).parents[1] root = Path(__file__).parents[1]
config = json.loads((root / "opencode" / "opencode.json").read_text()) config = json.loads((root / "opencode" / "opencode.json").read_text())
assert config["permission"] == "allow" assert "permission" not in config
assert all( assert all(name not in config["agent"] for name in ("build", "plan", "general"))
config["agent"][name]["permission"] == "allow" assert "permission" not in config["agent"]["explore"]
for name in ("build", "plan", "general", "explore")
)
assert config["agent"]["research"]["permission"] == { assert config["agent"]["research"]["permission"] == {
"*": "deny", "*": "deny",
"websearch": "allow", "websearch": "allow",