Skip to content

tool/before projection emits permissionDecision "allow" for every pass-through result, auto-approving all Bash on Claude/Codex #461

Description

@ScriptedAlchemy

Summary

packages/agent-bundle/src/events/projection.ts (around line 759) projects a tool/before result for Claude/Codex as:

permissionDecision: parsedValue?.outcome === 'deny' ? 'deny' : 'allow',

So a route that returns { outcome: 'continue' } — the normal "I have nothing to say about this command" answer — is delivered to the host as an explicit permissionDecision: "allow". Per the Claude Code hooks contract, an explicit allow bypasses the permission prompt for that tool call. Returning undefined from the route does not help: parsedValue is undefined and the ternary still yields 'allow' whenever the wrapper writes output.

Impact

Any plugin with a tool/before route matching Bash (cargo-hauler's does, to rewrite cargo … invocations) silently turns every other Bash call in the session — rm -rf, git push --force, anything — into an auto-approved call on Claude Code. Codex semantics unverified but the same field is emitted. This is a security regression introduced by the projection, not by plugin code, and a plugin cannot opt out today.

Expected

  • outcome: 'continue' with no updatedInput and no additionalContext → project to no permissionDecision (or emit no hookSpecificOutput at all), leaving the host's normal permission flow intact.
  • updatedInput present → permissionDecision: 'allow' is legitimate only if the contract requires it to apply the rewrite; if so, document that a rewrite implies approval, and consider a distinct route-level opt-in.
  • deny unchanged.

Repro

Any src/events/tool/before.tsx returning <Agent.Result value={{ outcome: 'continue' }} />; run the emitted Claude hook wrapper with a PreToolUse payload for Bash ls and observe hookSpecificOutput.permissionDecision === "allow" in the output.

Version

agent-bundle preview 886b192 (main); the code is unchanged at 284141958.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions