commit 09379de9e5e6ec0304a6118227b743323f218779
parent 0bff3355bbc7c9ab1fd4d60b8f60c715aa027ed7
Author: Anders Hedman <anders.hedman01@gmail.com>
Date: Thu, 24 Sep 2026 19:07:56 +0200
fix(opencode): gate abuse flags and secret paths
Restrict git branch/remote allows to read-only forms and demote git fetch to ask, so branch -D, remote set-url and fetch no longer auto-run. Deny git --output (writes files outside edit gating) and rg --pre (executes helpers).
Widen ~/.ssh, ~/.aws, ~/.gnupg and ~/.kube denies to cover the bare dirs, and deny credential stores (git-credentials, netrc, npmrc, pypirc, docker, cargo, gh, gcloud, opencode auth) and shell history files.
Diffstat:
1 file changed, 38 insertions(+), 8 deletions(-)
diff --git a/.config/opencode/opencode.jsonc b/.config/opencode/opencode.jsonc
@@ -122,9 +122,17 @@
{ "action": "shell", "resource": "git log*", "effect": "allow" },
{ "action": "shell", "resource": "git grep*", "effect": "allow" },
{ "action": "shell", "resource": "git show*", "effect": "allow" },
- { "action": "shell", "resource": "git fetch*", "effect": "allow" },
- { "action": "shell", "resource": "git branch*", "effect": "allow" },
- { "action": "shell", "resource": "git remote*", "effect": "allow" },
+ // git branch/remote: read-only forms only — no -D/-f/-m/--delete, no add/remove/set-url
+ { "action": "shell", "resource": "git branch", "effect": "allow" },
+ { "action": "shell", "resource": "git branch --list*", "effect": "allow" },
+ { "action": "shell", "resource": "git branch -a", "effect": "allow" },
+ { "action": "shell", "resource": "git branch -r", "effect": "allow" },
+ { "action": "shell", "resource": "git branch -v", "effect": "allow" },
+ { "action": "shell", "resource": "git branch -vv", "effect": "allow" },
+ { "action": "shell", "resource": "git branch -av", "effect": "allow" },
+ { "action": "shell", "resource": "git remote", "effect": "allow" },
+ { "action": "shell", "resource": "git remote -v", "effect": "allow" },
+ { "action": "shell", "resource": "git remote get-url*", "effect": "allow" },
{ "action": "shell", "resource": "git stash list*", "effect": "allow" },
// test / check commands
{ "action": "shell", "resource": "npm test*", "effect": "allow" },
@@ -140,6 +148,8 @@
{ "action": "shell", "resource": "git add*", "effect": "ask" },
{ "action": "shell", "resource": "git commit*", "effect": "ask" },
{ "action": "shell", "resource": "git push*", "effect": "ask" },
+ // network + writes .git
+ { "action": "shell", "resource": "git fetch*", "effect": "ask" },
{ "action": "shell", "resource": "git reset*", "effect": "ask" },
{ "action": "shell", "resource": "git checkout*", "effect": "ask" },
{ "action": "shell", "resource": "git clean*", "effect": "ask" },
@@ -192,6 +202,10 @@
{ "action": "shell", "resource": "rg* *.tfstate*", "effect": "deny" },
// Sops
{ "action": "shell", "resource": "sops*", "effect": "deny" },
+ // read-only flags that exec a helper or write files
+ { "action": "shell", "resource": "git* --output*", "effect": "deny" },
+ { "action": "shell", "resource": "rg* --pre *", "effect": "deny" },
+ { "action": "shell", "resource": "rg* --pre=*", "effect": "deny" },
// destructive: never auto-run (after the broader asks above)
{ "action": "shell", "resource": "rm -rf*", "effect": "deny" },
{ "action": "shell", "resource": "rm -fr*", "effect": "deny" },
@@ -208,12 +222,28 @@
{ "action": "external_directory", "resource": "*", "effect": "ask" },
{ "action": "external_directory", "resource": "/tmp/opencode/*", "effect": "allow" },
{ "action": "external_directory", "resource": "~/.config/opencode/skills/*", "effect": "allow" },
- { "action": "external_directory", "resource": "~/.aws/*", "effect": "deny" },
- { "action": "external_directory", "resource": "~/.gnupg/*", "effect": "deny" },
- { "action": "external_directory", "resource": "~/.kube/*", "effect": "deny" },
+ // credential stores, API tokens, and shell history (secrets pasted into commands)
+ { "action": "external_directory", "resource": "~/.aws*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.gnupg*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.kube*", "effect": "deny" },
{ "action": "external_directory", "resource": "~/.s3cfg*", "effect": "deny" },
- { "action": "external_directory", "resource": "~/.ssh/*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.ssh*", "effect": "deny" },
{ "action": "external_directory", "resource": "~/.vault_pass.txt*", "effect": "deny" },
- { "action": "external_directory", "resource": "~/.vault-token*", "effect": "deny" }
+ { "action": "external_directory", "resource": "~/.vault-token*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.git-credentials*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.netrc*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.npmrc*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.pypirc*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.docker*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.cargo/credentials*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.config/gh*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.config/gcloud*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.config/opencode/auth.json*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.local/share/opencode/auth.json*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.claude/.credentials.json*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.bash_history*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.zsh_history*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.python_history*", "effect": "deny" },
+ { "action": "external_directory", "resource": "~/.node_repl_history*", "effect": "deny" }
]
}