Skip to content

fix(agent-core-v2): refuse, don't hang, when approval is needed unattended - #10

Merged
devGregA merged 1 commit into
mainfrom
fix/headless-approval-deny
Aug 13, 2026
Merged

fix(agent-core-v2): refuse, don't hang, when approval is needed unattended#10
devGregA merged 1 commit into
mainfrom
fix/headless-approval-deny

Conversation

@devGregA

Copy link
Copy Markdown
Contributor

Problem — a regression from the hardening work, found by running the CLI

Excluding Bash from auto-mode approval (PR #5) left headless runs in a state nothing could resolve: kimi -p forces auto mode, the model calls Bash, the policy chain falls through to an ask — and a print-mode session has no UI to answer it. The process hangs forever.

This was not visible in the unit tests, because there the approval broker is absent and the fail-closed path (PR #2) returns a refusal. In a real session the broker is bound; it just never gets an answer.

Reproduced against a built CLI driven by a stub model endpoint: the run was still alive after 60s and had to be killed. Test suites were green throughout — this only shows up when the binary actually runs.

What changed

  • An ask in auto mode now resolves as a refusal instead of going to the broker. Auto mode is documented as "fully autonomous, the agent will not ask questions", so the request cannot be answered by definition. This reuses the existing fail-closed branch rather than adding a second path, and the message names the tool and points at the [permission] allow rule so an unattended pipeline fails with something actionable. It mirrors auto-mode-ask-user-question-deny, which already solves exactly this for AskUserQuestion.
  • FetchURL added to the auto-mode exclusion set. It was removed from the default approve set in PR chore(hardening): stop auto-approving Bash in auto mode and FetchURL by default #5, but auto mode still approved it, so headless runs could still send caller-chosen bytes to a caller-chosen host unprompted. Safe to close now that an unreachable ask fails fast instead of hanging.

Verified against the built CLI

Driven end-to-end through dist/main.mjs against a local stub model endpoint (no credentials), in an isolated KIMI_CODE_HOME:

probe before after
Bash in -p hangs indefinitely exits cleanly, refused with guidance
FetchURL in -p executed unprompted refused with guidance
Read of an ordinary file works works

Also confirmed unchanged in the same harness: symlink escape refused, .env refused, package.json write refused, and a [[permission.rules]] deny rule refusing the named tool.

Testing

  • New unit test: in auto mode the broker is never called and the result is a veto mentioning "unattended".
  • Full agent-core-v2 suite green: 310 files / 4906 tests.
  • oxlint clean on changed files (one pre-existing warning elsewhere); tsc --noEmit clean.

Checklist

  • Problem explained above.
  • Tests added that prove the change works.
  • Changeset added (patch).
  • No doc update needed.

…ended

Excluding Bash from auto-mode approval left headless runs with a tool that
falls through to an ask — and nothing in a `kimi -p` session can answer
one, so the process waited forever instead of finishing. Verified against
a built CLI: the run never exited.

Auto mode is documented as never asking questions, so treat it the way a
missing broker is already treated and resolve the request as a refusal.
The message names the tool and points at the [permission] allow rule, so
an unattended pipeline fails with something actionable rather than
hanging. This mirrors auto-mode-ask-user-question-deny, which solves the
same problem for AskUserQuestion.

Add FetchURL to the auto-mode exclusion set while the behaviour is safe to
extend: it is the tool that sends caller-chosen bytes to a caller-chosen
host, and an unattended session is where that would go unnoticed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@devGregA
devGregA merged commit 7557aa5 into main Aug 13, 2026
14 checks passed
@devGregA
devGregA deleted the fix/headless-approval-deny branch August 13, 2026 15:19
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.

1 participant