You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
bug(approvals): the resubmit path skips action validation, so a target can change after a human reviewed it #17349
#17315 / PR #17323 close the unregistered-action hole on POST /approval-gates by routing it through _reject_unregistered_action. The resubmit path is a second entry point to the same defect and was not covered, because it is pre-existing code the PR did not touch.
Found during the pre-merge review of #17323. Not a regression from that PR, and explicitly not a fail-open of the deletion gate — see scope below.
The subtler one, and the reason this is worth more than a tidy-up. For an action that is registered and destructive, a caller can swap the provider / candidate_idbetween a human's revision request and their subsequent approve. The human reviews one target and approves a different one. The approval record and the audit trail both stay internally consistent, so nothing downstream looks wrong — the substitution is invisible at the point it matters.
Scope — what this is not
Deletion still requires the unchanged require_interactive_human-gated approve() call (api/approval_gates.py:220-221, #17042), and execute_orphan_storage_delete re-validates provider and candidate at execution time rather than trusting the proposal. So this does not let anyone delete without a human, and #17038 is not breached. It lets a caller change what the human is approving after they have looked at it.
Acceptance criteria
resubmit rejects an unregistered context.action through the same _reject_unregistered_action path as POST /approval-gates, with the same status and detail.
A test asserts the specific refusal — exact status code and detail substring — and that no state transition is recorded. Not != 200.
An ownership or authorship check governs who may resubmit a given approval.
For an already-registered destructive action, a test asserts that resubmit cannot change provider / candidate_id after a revision request — or, if changing them is intended, that doing so resets the approval to PENDING so the human re-reviews the new target rather than approving the old one.
Follow-up from #18453 (merged approach): resubmit now locks context.action and every reviewed field (context_change_violation), and only the original requester may resubmit. Remaining LOW: the requester match compares the verified id or the username (or its suffix after the last colon) against requested_by_agent. With the action and reviewed fields frozen, this only governs who may edit description and free text, but it should match on the verified user id only, as #18453's decide fix does.
Activity
fix(approvals): resubmit may not rewrite a reviewed proposal, and onl…
mrveiss commentedon Oct 12, 2026
Follow-up from #18453 (merged approach): resubmit now locks
context.actionand every reviewed field (context_change_violation), and only the original requester may resubmit. Remaining LOW: the requester match compares the verified id or the username (or its suffix after the last colon) againstrequested_by_agent. With the action and reviewed fields frozen, this only governs who may edit description and free text, but it should match on the verified user id only, as #18453's decide fix does.