Skip to content

Scope Always allow to a command prefix instead of the whole tool - #1666

Merged
currentbits merged 2 commits into
mainfrom
coder/allow-always-is-a-command-prefix-not-the-f7db60
Oct 18, 2026
Merged

currentbits merged 2 commits into
mainfrom
coder/allow-always-is-a-command-prefix-not-the-f7db60

Conversation

@currentbits

Copy link
Copy Markdown
Owner

Accepting npm test with "Accept all" used to add a whole-tool session rule, so every later Bash call in that session ran unasked, rm -rf included. Always allow now grants Bash(npm test:*), which is what the CLIs themselves offer. Allowing the whole tool is an explicit choice you have to pick. Closes #479.

Changes

  • Button: on a Claude command the card shows Always allow npm test:*. The rule is derived from the command that will actually run, so it updates when you edit the command.
  • Overflow: a collapsed "Always-allow options" section lets you type your own rule, e.g. npm run *, and holds a red Allow any Bash this session button. That button is the only way to get a whole-tool rule.
  • Narrow default everywhere: the main process also derives the prefix itself when no rule is sent, so orchestration, the web bridge and older clients stop granting whole-tool too.
  • Event log: the conversation event records the rule that was granted, e.g. Allowed for session: Bash: npm test (rule: npm test:*).
  • Unchanged: tools without a command (Edit, Write) still allow the whole tool. Codex keeps "Accept all", because acceptForSession already covers only that exact command.

Verification

  • npm run typecheck passes and npx vite build succeeds.
  • Electron: every test file that exercises respondPermission, including the governance, guardrails, codex-approvals and orch-merge tests, passes 177/0 after rebasing onto main.
  • New tests check that accepting npm test -- foo sends ruleContent: "npm test:*" and not a whole-tool rule. They also cover a typed rule, * meaning the whole tool, and an empty typed rule falling back to the prefix.
  • Renderer: threadView, permissionPrompt and the new permissionRuleParity tests pass. Card tests cover the rule following command edits, a typed rule surviving later edits, an empty rule disabling the button, the overflow sending *, and profile.ask hiding every always-allow option.
  • Before the rebase, the full test:electron run ended at 4738 passing and 19 failing. The failures were in grok MCP registration, codex usage and worktree tests, none of which load these files. Rerun on their own, those files pass 146/0 both on this branch and on an unmodified HEAD.
  • Not tested: clicking through a live Claude CLI session in the app.

Notes for reviewers


claude-opus-5-5 via Claude Code

🤖 Generated with Claude Code

Accept all on a Claude command used to add a whole-tool session rule, so
allowing `npm test` also allowed `rm -rf` for the rest of the session.
Allow-always now sends a prefix rule (`npm test:*`) derived from the
command that runs, or a rule the user typed; the whole tool is an
explicit "Allow any <tool> this session" overflow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-18T20:01:54.825040Z 266ff9f PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

if (TWO_TOKEN_BINS.has(bin) && tokens[1] && !tokens[1].startsWith("-")) {
prefix = `${tokens[0]} ${tokens[1]}`;

P1 Badge Put the wildcard after the actual operation

For commands whose operation appears after a dispatcher or global option, this two-token heuristic creates a much broader grant than the approved command: npm run test becomes npm run:*, while git -C repo status becomes git:*. Claude documents that npm run * matches every npm script and that git * permits every git subcommand, so later deploy, publish, push, or other mutating commands can run without another prompt. Parse through dispatcher verbs and global options, or fall back to a narrower exact rule, before appending the wildcard. Claude Code wildcard-rule documentation


const withoutEnv = trimmed.replace(
/^(?:[A-Za-z_][A-Za-z0-9_]*=\S*\s+)+/,
"",

P2 Badge Preserve environment assignments Claude does not strip

For a command such as FOO=bar npm test, this removes the assignment and stores npm test:*, but Claude only strips a fixed set of known-safe environment variables when matching allow rules; an arbitrary variable prevents that rule from matching. Consequently, clicking “Always allow” for such a command still produces another prompt on the identical next invocation. Only remove variables from Claude's safe allowlist, or retain unknown assignments in the derived rule. Claude Code wrapper and environment matching documentation

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@currentbits
currentbits merged commit 3935629 into main Oct 18, 2026
6 checks passed
currentbits pushed a commit that referenced this pull request Oct 18, 2026
… n / a on top

#1666 landed #479 on main with the same shape as this branch's narrowing
(alwaysRule, "*" for the whole tool). Take main's backend, IPC and card
UI as-is; this branch now only adds the keyboard layer (#477): y / n / a
on permission and plan cards, key hints, the composer marker, and tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
currentbits pushed a commit that referenced this pull request Oct 19, 2026
… n / a on top

#1666 landed #479 on main with the same shape as this branch's narrowing
(alwaysRule, "*" for the whole tool). Take main's backend, IPC and card
UI as-is; this branch now only adds the keyboard layer (#477): y / n / a
on permission and plan cards, key hints, the composer marker, and tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow-always is a command prefix, not the whole tool

1 participant