Skip to content

allowed-tools on the four actionability-gate consumers is too wide (python3/git pre-approval) and too narrow (gate block source line, idd-plan's non-Bash tools) #341

Description

@kiki830621

Problem

The four actionability-gate consumers (idd-list, idd-all, idd-implement, and — since round 4 of PR #318 — idd-plan) share one allowed-tools list:

allowed-tools:
  - Bash(gh:*)
  - Bash(git:*)
  - Bash(jq:*)
  - Bash(python3:*)

It is wrong in both directions at once.

Too wide. Bash(python3:*) pre-approves python3 -c '<anything>', Bash(git:*) pre-approves git -c core.pager='!sh -c …', and Bash(gh:*) covers every write sub-command plus gh auth token. On idd-plan this sits directly against the skill's value proposition (nothing stateful before the plan is approved). scripts/tests/actionability-gate/test.sh:393-395 currently asserts that each consumer contains Bash(python3:*), so the width is pinned. idd-ask already shows the narrow form (Bash(gh issue view:*), Bash(gh search:*)).

Too narrow. The reference says the list exists "so unattended runs do not stall on a permission prompt", but the gate block's first command is . "$CLAUDE_PLUGIN_ROOT/scripts/lib/actionability.sh" || { … } — none of the four prefixes matches it, so unattended runs still stall exactly where the list promised they would not. idd-plan additionally lacks Read, EnterPlanMode / ExitPlanMode (Step 4 — the reason the skill exists), AskUserQuestion, TaskCreate / TaskUpdate, Skill; idd-implement and idd-all list those.

allowed-tools is pre-approval, not restriction (official docs: it does not restrict which tools are available), so nothing is broken today — the list simply fails to do what the contract says it is for, on three consumers before round 4 and on four after.

Source

Expected

One list, derived from what the gate block and each skill actually run, applied to all four consumers:

  • Bash prefixes narrowed to the commands used: Bash(gh api:*), Bash(gh issue view:*), Bash(gh issue list:*) (idd-list), Bash(jq:*); python3 restricted to the skill's own script path or removed if the inline snippet moves into scripts/lib/; git only where a consumer actually runs it (idd-implement's branch creation), never on idd-plan.
  • The gate block's source line covered — either a prefix form the permission matcher accepts for . path, or the block rewritten to invoke a named script so Bash(bash $CLAUDE_PLUGIN_ROOT/scripts/*)-style matching applies. Verify the chosen form against the permissions reference before committing to it.
  • idd-plan gains the non-Bash tools it calls: Read, EnterPlanMode, ExitPlanMode, AskUserQuestion, TaskCreate, TaskUpdate, Skill.
  • test.sh:393-395 asserts the narrowed set and refutes Bash(python3:*) / bare Bash(git:*) on idd-plan.

Acceptance criteria

  • the four consumers share one narrowed allowed-tools list; no Bash(python3:*) on any of them
  • the gate block's first command matches a listed prefix (or the block is a named script that does)
  • idd-plan lists every non-Bash tool its steps invoke
  • the drift guard in test.sh pins the narrowed list and refutes the wide prefixes

Complexity

Simple — four frontmatter edits and one assertion; the only open question is which prefix form matches a . path source line, and that is a documentation lookup, not a design decision.

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

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions