Skip to content

fix(acp): gate patch mode=patch (V4A) behind ACP edit approval#28120

Open
EloquentBrush0x wants to merge 1 commit into
NousResearch:mainfrom
EloquentBrush0x:fix/acp-edit-approval-v4a-patch
Open

fix(acp): gate patch mode=patch (V4A) behind ACP edit approval#28120
EloquentBrush0x wants to merge 1 commit into
NousResearch:mainfrom
EloquentBrush0x:fix/acp-edit-approval-v4a-patch

Conversation

@EloquentBrush0x

Copy link
Copy Markdown
Contributor

Problem

patch with mode="patch" (V4A multi-file format) silently bypassed the ACP edit approval guard introduced in #27862.

build_edit_proposal handled write_file and patch mode=replace, but returned None for mode=patch. maybe_require_edit_approval treats None as "no approval needed" and lets dispatch continue — so an ACP session under the default Ask policy would never prompt before a V4A patch executed.

The intent to gate both tool types is visible in model_tools.py: the exception-path deny covers {"write_file", "patch"} together, but the normal path missed mode=patch.

Fix

  • build_edit_proposal — adds _proposal_for_patch_v4a branch so the approval requester is always called for V4A patches.
  • build_acp_edit_tool_call — detects V4A proposals and renders per-file tool_diff_content blocks (mirroring _build_patch_mode_content), so the Zed dialog shows a structured diff rather than raw patch text.
  • should_auto_approve_edit — short-circuits on V4A proposals: workspace_session prompts (can't verify per-file containment without parsing every operation); session auto-approves (symmetric with single-file behaviour).

No behaviour change for CLI/gateway sessions where the ContextVar is unset.

Tests

test what it covers
test_patch_v4a_rejection_does_not_mutate requester=False → file not written, error returned
test_patch_v4a_approval_request_captures_proposal requester is called with correct tool_name and mode
test_patch_v4a_tool_call_uses_per_file_diff_content build_acp_edit_tool_call emits per-file blocks (skipped without ACP SDK)
test_patch_v4a_auto_approval_* should_auto_approve_edit policy matrix for V4A

Fixes approval bypass introduced in #27862.

patch mode="replace" and write_file were correctly gated; mode="patch"
(V4A multi-file format) returned None from build_edit_proposal, which
maybe_require_edit_approval treated as "no approval needed", silently
bypassing the guard regardless of the user's edit-approval policy.

Fix: route mode="patch" through _proposal_for_patch_v4a so the approval
requester is always invoked for V4A patches.  build_acp_edit_tool_call
renders per-file diff blocks (mirroring _build_patch_mode_content) so
the Zed approval dialog shows a structured diff rather than raw patch
text.  should_auto_approve_edit now short-circuits on V4A proposals:
workspace_session policy prompts (can't verify per-file containment);
session policy auto-approves (symmetric with single-file behaviour).

No behaviour change for CLI/gateway sessions where the ContextVar is
unset.

Fixes approval bypass introduced in NousResearch#27862.
@BoardJames-Bot

Copy link
Copy Markdown

BoardJames CI triage for the current head (7d839688): most hosted checks are already green (nix macOS/Ubuntu, lint, supply-chain, e2e, build-amd64); build-arm64 and full Tests / test are still in progress.

One branch-local issue I can reproduce on macOS before the full suite finishes:

python -m pytest tests/acp/test_edit_approval.py -q -o 'addopts='
# 4 failed, 10 passed

The failures are from the new ACP edit-approval tests using pytest tmp_path under macOS /var/folders/..., which resolves to /private/var/folders/...; handle_function_call then rejects the edit as a sensitive system path before approval can mutate the temp file. The new should_auto_approve_edit /tmp/ check has the same canonicalization problem: /tmp/... resolves to /private/tmp/..., so str(path).startswith("/tmp/") is false on macOS.

Suggested owner fix: either keep these approval-path tests inside a repo/workspace temp directory that the file tool allows, or canonicalize the temp-root allowance with Path("/tmp").resolve() / platform tempdir containment instead of a raw /tmp/ string prefix. I did not push because this is a cross-repo contributor branch.

@alt-glitch alt-glitch added type/security Security vulnerability or hardening P2 Medium — degraded but workaround exists comp/acp Agent Communication Protocol adapter tool/file File tools (read, write, patch, search) labels May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/acp Agent Communication Protocol adapter P2 Medium — degraded but workaround exists tool/file File tools (read, write, patch, search) type/security Security vulnerability or hardening

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants