fix: opencode config 2
This commit is contained in:
@@ -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
@@ -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.",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user