Repository navigation
Description
Summary
On 0.0.0-beta-19151, an ask verdict set by a permission.evaluate plugin hook is ignored: the tool executes as if allowed and no prompt ever surfaces. A deny verdict from the same hook is still honored (permission.rejected). Any plugin implementing approval policies through this hook (ask-tier) is therefore silently bypassed on this beta, while deny-tier keeps working.
Environment
- opencode version:
opencode2 v0.0.0-beta-19151 - OS: macOS, Darwin 25.5.0 (darwin arm64)
- Terminal: VS Code integrated terminal (
TERM_PROGRAM=vscode,TERM=xterm-256color) - Shell:
/bin/zsh - Install/channel: beta
- Active plugins: one local file plugin (
~/.config/opencode/plugins/security-guard.js, V2 object form) plus, during the investigation only, a minimal tap plugin (removed afterwards; production state restored and verified healthy viascripts/doctor.mjs --live)
Reproduction
-
Install a minimal tap plugin (V2 object form) at
~/.config/opencode/plugins/zzz-eval-tap.js:import { appendFileSync } from "node:fs" export default { id: "zzz-eval-tap", async setup(ctx) { await ctx.permission.hook("evaluate", (event) => { try { const res = Array.isArray(event?.resources) ? event.resources : [] if (res.some((r) => String(r).includes("CANARY-ASK-TEST")) && event) { event.effect = "ask" event.message = "tap canary: direct ask, no plugin logic involved" } if (res.some((r) => String(r).includes("CANARY-DENY-TEST")) && event) { event.effect = "deny" event.message = "tap canary: direct deny, no plugin logic involved" } appendFileSync("/tmp/eval-tap.log", JSON.stringify({ action: event?.action, effect: event?.effect, n: res.length, }) + "\n") } catch {} }) }, }
-
Restart the service (
opencode2 service restart). -
In an agent session, run
echo CANARY-ASK-TEST. -
Observe: the command executes (
CANARY-ASK-TESTis printed, no prompt), while/tmp/eval-tap.logcontains{"action":"shell","effect":"ask","n":…}— proving the hook fired and the ask verdict was recorded, then ignored. -
Run
echo CANARY-DENY-TEST. Observe: the command is blocked withpermission.rejectedcarrying the tap message —denyis honored.
Expected Behavior
An ask verdict set by a permission.evaluate hook produces an approval prompt (the behavior on 0.0.0-beta-19086 for non-cd commands, per #47356), blocking execution until the user responds.
Actual Behavior
The ask verdict is silently dropped: execution proceeds as if the effect were allow. Consistently reproducible across many commands and several service restarts. deny from the same hook works correctly, and tool.execute.before throws still block — the gap is specific to the ask effect of the permission pipeline.
Impact: every ask-tier policy implemented via permission.evaluate (approval prompts for ambiguous operations) silently becomes allow on this beta. Only deny-tier enforcement can be relied on.
Additional Context
- Related: plugin: permission.evaluate hook does not fire for cd-led shell commands #47356 (
permission.evaluatenot firing forcd-led commands on beta-19086 — same channel family, one beta earlier). - Secondary observation: on beta-19151, shell
resourcesarrive pre-segmented — one resource per;-segment (echo a; echo byieldsn:2; a 4-statement command yieldedn:4). The deny canary confirms adenyon the whole event still blocks the full command. Plugin authors matching whole-command patterns againstresourcesshould be aware the unit changed from whole-command (19086) to per-segment (19151). - Service log note: per-command
evaluated permission=…INFO lines present on older betas no longer appear at all on 19151 (onlyspawning processlines), consistent with an evaluation-pipeline change. - Workaround used by the affected plugin: enforce ask-tier verdicts for shell commands as hard blocks inside
tool.execute.before(which still throws reliably), at the cost of losing the approve-and-continue workflow for legitimate ambiguous operations. - Evidence method: tap log lines plus observed command outcomes; the tap plugin was removed and the service restarted afterwards (only the production plugin remains;
doctor --livehealthy).
Activity
github-actions commentedon Sep 5, 2026
This issue might be a duplicate of existing issues. Please check:
askexecutes without prompting (different trigger path, config-level rules)askpermission bypassed for plugin tools via theexecutedispatcher in Code ModeIf your issue is distinct from these (the regression appears specific to
beta-19151and thepermission.evaluatehook path), a maintainer may want to link them as related.whepper commentedon Sep 5, 2026
Thanks for the triage — I checked both, and this looks distinct but related rather than a duplicate. Suggest linking as related instead of closing:
vs #45932 — different version line, trigger path, and reproducibility:
1.18.25, Fedora, TUI session) going through native config rules (permission.bash), and is intermittent ("usually this does not happen").0.0.0-beta-19151) going through the pluginpermission.evaluatehook, with no config rules involved, and is 100% deterministic via a 10-line tap plugin.vs #47177 — different trigger path and a sharper bisection:
executedispatcher skipping asks for nested plugin-tool calls, where direct calls still prompt.effect = "deny"blocks correctly (permission.rejectedwith the plugin message), whileeffect = "ask"executes as if allowed. There is also a clean regression window: asks prompted normally onbeta-19086(see plugin: permission.evaluate hook does not fire for cd-led shell commands #47356, same channel family) and are ignored onbeta-19151.Common thread worth linking: all three are ask-enforcement failures, so a shared root cause in permission-effect handling can't be ruled out. But the trigger paths, versions, and determinism differ enough that a duplicate closure would lose the hook-path minimal repro. Happy to re-test against a newer beta or provide tap logs.
docs(verification): permission.evaluate ask verdicts ignored on beta-…
rekram1-node commentedon Oct 14, 2026
opencode-agent can u reproduce?
rekram1-node commentedon Oct 14, 2026
I checked this against current dev and couldn't reproduce it. With a permission.evaluate hook setting ask on an otherwise allowed shell command, the request shows up as a prompt and the command waits until it's answered. The engine already handled ask this way on the beta you were using, so something likely answered the prompt automatically before you saw it. That could be the TUI running in auto accept mode (--auto or session.permissions set to autoaccept), the Desktop issue in #54790, or another plugin replying to permission requests. I'm going to close this for now, but please reopen it if you can still reproduce it with the TUI in normal prompt mode.