continuedev / continuedev/continue

CLI: 'ask' permission tier silently auto-denies when onToolPermissionRequest callback isn't wired, mislabeled as user denial

Open
#13,178 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
36k
Forks
5.4k
PR merge metrics
No merged PRs in 30d

Description

Before submitting your bug report
  • I've tried finding an answer on the Continue docs site
  • I'm not able to find an open issue that reports the same bug (searched: "permission denied", "onToolPermissionRequest", "denialReason", "CLI permission", "tool call denied" — closest related but distinct: #13001, #12963)
  • I've seen the troubleshooting guide on the Continue Docs
Relevant environment info
  • OS: Linux
  • Continue version (CLI): 1.5.47
  • Node: v22.15.0
Description

Summary

In @continuedev/cli, tool calls with an ask-tier permission policy sometimes get silently denied with no interactive prompt ever shown to the user. The denial is then reported with denialReason:"user", which is misleading — the user was never actually asked.

Root cause (from reading the bundled dist/index.js)

The permission-decision function resolves an ask policy by calling into the prompt-request function:

async function _ua(e,t,n,r){
  let o=VXe(t,e);
  return o.permission==="allow" ? {approved:!0}
    : o.permission==="ask" ?
        (r ? {approved:!1,denialReason:"policy"}
           : await Eua(t,n) ? {approved:!0}
           : {approved:!1,denialReason:"user"})
    : o.permission==="exclude" ? {approved:!1,denialReason:...}
    : ...
}

And the actual prompt function:

async function Eua(e,t){
  if(!t?.onToolPermissionRequest) return !1;
  let n={name:e.name,arguments:e.preprocessResult?.args??e.arguments,preview:e.preprocessResult?.preview, ...};
  ...
}

If t.onToolPermissionRequest is not attached for a given tool call, Eua returns false immediately — no prompt is ever rendered — and the caller reports denialReason:"user" even though the user was never asked.

Steps to reproduce

  1. Run cn interactively (not headless, no -p/--print)
  2. Configure permissions.yaml such that some tool/Bash patterns are unmatched by allow/ask/exclude, falling through to the default "ask" policy
  3. Trigger a tool call matching one of those unmatched patterns (e.g. a Bash command not covered by any allow rule)
  4. Observe: the tool call is denied with no interactive prompt ever appearing, and the denial is reported as if the user rejected it

Expected behavior

An ask-tier permission should always show the interactive prompt when not in headless mode. If the callback isn't available, that's an internal wiring bug and should either surface an error/warning rather than silently denying, or the denial reason should reflect the actual cause (e.g. "callback_missing") instead of being mislabeled "user".

Additional context

We also intermittently saw "Message splitting exceeded maximum iterations, stopping" in the same sessions where this occurred, which may point to broader instability in the TUI's message/callback event loop — possibly a related root cause (the same callback-wiring issue affecting more than just the permission prompt).

Workaround

Expanding permissions.yaml's allow list to explicitly cover the needed command patterns (e.g. Bash(pio*), Bash(ufbt*), Bash(git*)) avoids the broken ask path entirely, since allow short-circuits before Eua is ever called.

Related issues (not duplicates, but adjacent)

  • #13001 — incomplete destructive-command blocklist causing the opposite failure mode (unwanted auto-execution) in headless/auto mode
  • #12963 — malformed message structure after a tool request is cancelled, a different bug in the same general tool-call/permission code path
To reproduce

See "Steps to reproduce" above.

Log output

N/A — no error is logged; the tool call is simply denied with denialReason:"user" and no prompt is shown.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the permission-decision and prompt functions in the bundled dist/index.js, focusing on onToolPermissionRequest and the default ask policy from permissions.yaml. Reproduce an unmatched tool pattern in interactive CLI mode, then verify that ask requests are prompted or that a missing callback is surfaced distinctly from a user denial.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
authorization, cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.