VS Code extension: PreToolUse 'ask' permission tier (static rules + hooks) silently resolves to allow, no prompt shown

Status Open
Reported on v2.1.198
Maintainer reply None cached
Activity 0 comments · opened Aug 14, 2026

Summary

In the VS Code extension (default permission mode), a tool call that should be escalated to a permission prompt — because it matches a static "ask" permission rule, or because a PreToolUse hook returned hookSpecificOutput.permissionDecision: "ask" — instead runs immediately with no prompt shown to the user. The same rule/hook combination behaves correctly (blocks in headless, and per our reading of the docs, should prompt interactively) when reproduced via the headless CLI.

This means an "ask"-tier permission control (static rule or hook) is currently a silent no-op in the VS Code extension's default permission mode — it neither blocks nor visibly prompts; the tool call simply proceeds as if it had been allowed.

Environment

  • Claude Code CLI 2.1.198
  • VS Code extension, recorded session permissionMode: "default"
  • Reproduced with both (a) a static settings.json permission rule of the "ask" tier, and (b) a PreToolUse hook returning permissionDecision: "ask"

Headless baseline (behaves as documented)

Using claude -p in isolated temp projects, permission precedence matched the documented order (deny → ask → allow) in every case we tried:

  1. A settings allow: ["Bash(echo:*)"] rule plus a PreToolUse hook returning permissionDecision: 'ask' for the same command → the call is blocked (headless can't prompt, so it fails closed) with the hook's stated reason. Hook-ask correctly overrides a standing allow rule.
  2. Same result under --permission-mode bypassPermissions — hook-ask still blocks headless.
  3. A static "ask" rule correctly overrides a same-scope "allow" rule.
  4. A static "ask" rule correctly overrides a broader-scope "allow" rule (project-level ask vs. user-level allow).

So headless enforcement of the ask tier — both static rules and hook-emitted decisions — matches the documented precedence in every combination we tested.

VS Code extension (diverges from the above)

In a live, interactive VS Code extension session (same permission configuration, permissionMode: "default"):

  • A Bash command matching a project-level static "ask" rule (and matching no "allow" rule at any scope — checked user, project, and local settings) ran immediately, with no permission prompt.
  • The same result for a WebFetch call: a PreToolUse hook returned permissionDecision: "ask" for a non-allowlisted host, and the fetch executed immediately with no prompt and no visible indication the hook's decision was overridden.
  • For comparison, "deny"-tier decisions (both a static deny rule and a hook returning permissionDecision: "deny") do work correctly in this same environment — those calls visibly block with the stated reason. Only the ask tier is affected.

Expected vs actual

  • Expected: a tool call matching an "ask"-tier decision (static rule or hook) shows the user a permission prompt in the VS Code extension, same as it does (per the docs) in other interactive contexts.
  • Actual: the entire ask tier is silently resolved to allow in the VS Code extension's default permission mode — no prompt, no log entry visible to the user, the call simply proceeds.

Impact

Any project relying on "ask"-tier permission rules or hook-emitted ask decisions as a safety control — expecting the user to be asked before a risky action proceeds — gets no protection at all in the VS Code extension, with no indication anything was skipped. We only discovered this by explicitly testing whether a prompt appeared; from the tool-call's perspective (exit code, hook stdout) everything looked like normal ask-path handling. We've had to work around this by defaulting the affected controls in our own hooks to hard-deny instead of ask, since ask currently provides no actual protection in this environment.

Suggested fix

Either make the VS Code extension's default permission mode surface the prompt for ask-tier decisions (matching headless/interactive-terminal behavior), or, if this is an intentional divergence for the extension, document it clearly so hook/rule authors don't unknowingly rely on ask as a working control there.

Happy to share the minimal repro harness (settings.json + hook scripts) if useful.

View original on GitHub ↗