Skip to content

Fix cutover exec-stack recursion and provider block handling - #263

Merged
paudley merged 3 commits into
mainfrom
fix/cutover-exec-stack-recursion
Jul 7, 2026
Merged

Fix cutover exec-stack recursion and provider block handling#263
paudley merged 3 commits into
mainfrom
fix/cutover-exec-stack-recursion

Conversation

@paudley

@paudley paudley commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Summary

This branch fixes two related runtime cutover failures in the hook/toolchain path:

  • Scrubs CODING_ETHOS_EXEC_STACK before sanctioned cutover child process execution so verification children do not trip recursive executable invocation protection.
  • Makes blocked agent-hook provider results exit nonzero even when JSON output is enabled, and updates probe assertions to match the live compiled policy shapes.
  • Tightens the affected tests around managed-lint target matching, hook CLI exit behavior, and provider block expectations.

Impact

make cutover-verify and cutover install paths should no longer fail because child commands inherit the parent exec guard stack, and raw provider block probes should no longer report an allowed command when the policy result is blocked.

Validation

  • git diff --check origin/main...HEAD
  • make build

Notes

The local checkout still has unstaged go.work.sum drift from Go workspace checksum updates. The branch commits and remote comparison do not include module metadata changes, so that file was left out of this PR.

paudley added 3 commits July 6, 2026 13:31
runCutoverCommand spawned coding-ethos-run children (agent-hooks verify,
policy-lint --scope cutover, git-hook validate) with the parent's full
environment, so they inherited CODING_ETHOS_EXEC_STACK and exited 96
(recursive coding-ethos executable invocation blocked), failing every
make cutover-verify and cutover-install run. Scrub the exec-guard stack
variable before spawning, matching the other sanctioned spawn paths in
mcp/cerun.go, gitwrap git_env.go, and agenthooks settings.go.

Also scope the managed-lint target assertion in main_test.go to the
argv after the -- separator: hook-managed sandboxes place go test
TMPDIR under the repo, so temp paths in --bundle/--ethos-root flags
legitimately contain the parent directory name and made the broad
substring check fail.
… shapes

hookcli returned exit 0 for blocked codex and gemini agent-hook results
whenever --json output was enabled (regression from 0a32d43), so
cutover-verify's codex raw git probe reported allow even though the
command was blocked. Blocked provider results now exit with the
blocked exit code regardless of output mode.

The codex probe validators also encoded remediation shapes that never
matched the live compiled bundle: stronger policies such as
git.checkout_protected_branch win over git.wrapper_required, and the
wrapper refusal path carries no cerun template. Probe validation is
now split into shape-specific checks (strict wrapper+cerun for plain
git, git.* block for protected-branch switch, wrapper refusal for
raw-path/bash-c/python-subprocess, hard block for tamper).
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6d03778a-5785-4f35-a1c6-a77eaf60dcb5

📥 Commits

Reviewing files that changed from the base of the PR and between efc7f2a and ac7d7ae.

📒 Files selected for processing (6)
  • go/cmd/coding-ethos-run/main_test.go
  • go/internal/agenthooks/settings.go
  • go/internal/e2e/agent_hook_test.go
  • go/internal/hookcli/main.go
  • go/internal/hookcli/main_internal_test.go
  • go/internal/toolchaincli/cutover_verify.go

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Hook blocking now exits consistently with the expected blocked status and shows advice only in non-JSON output.
    • Cutover verification no longer carries over environment state that could cause nested runs to block themselves.
    • Validation for blocked scenarios is now more precise, improving reliability across different denial cases.
  • Tests

    • Updated automated checks to better match the intended blocked exit behavior and avoid false failures.

Walkthrough

Refactors Codex block-probe validation in agenthooks into scenario-specific validators, updates hookcli to always return a fixed blocked exit code, adds matching e2e fixture exit-code expectations, filters exec-guard stack env vars in cutover verification's child process environment, and scopes a lint test's substring assertion to extracted targets.

Changes

Codex probe validation and blocked exit code consistency

Layer / File(s) Summary
Codex probe validators refactor
go/internal/agenthooks/settings.go
Replaces the single generic validateCodexBlockProbe with validateCodexGitPolicyBlockProbe, validateCodexWrapperRefusalProbe, validateCodexPolicyBlockProbe, and a shared validateCodexBlockReason helper that checks decision/reason and loops over caller-provided reason markers.
hookcli blocked exit code fix
go/internal/hookcli/main.go, go/internal/hookcli/main_internal_test.go
runWithIO now returns blockedExitCode directly for blocked results (removing blockedResultExitCode), and both bypass tests assert the exact blockedExitCode value.
e2e fixture exit-code expectations
go/internal/e2e/agent_hook_test.go
Codex pretool git denial and bypass denial fixtures now include wantExit: 1.

Cutover Verify Exec-Guard Env Isolation

Layer / File(s) Summary
Filter exec-guard env stack variable
go/internal/toolchaincli/cutover_verify.go
Imports execguard and builds the child command environment from os.Environ() excluding execguard.EnvStack-prefixed entries.

Lint Test Target-Scope Assertion Fix

Layer / File(s) Summary
Scope lint target assertions
go/cmd/coding-ethos-run/main_test.go
Extracts the target list after " -- " via strings.Cut and checks only that segment for "coding_ethos"/"missing" instead of the whole call output.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI as hookcli.runWithIO
  participant Result as HookResult
  participant Test as main_internal_test.go / e2e fixtures

  CLI->>Result: check result.Blocked()
  Result-->>CLI: true
  CLI->>CLI: optionally printBlocked (if not --json)
  CLI-->>Test: return blockedExitCode
  Test->>Test: assert status/wantExit == blockedExitCode
Loading

Suggested reviewers: ErinAudley

Poem

A rabbit hopped through code today,
Blocking exits the same clean way. 🐇
Env vars trimmed, no ghostly stack,
Lint targets checked, right on track.
Thump thump — ship it, no delay!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cutover-exec-stack-recursion

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linter] gci: create analyzer: finding local modules for localModule configuration: reading go.mod: open go.mod: no such file or directory"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@paudley
paudley marked this pull request as ready for review July 7, 2026 02:13
@paudley
paudley requested a review from ErinAudley as a code owner July 7, 2026 02:13
@paudley
paudley merged commit 5259447 into main Jul 7, 2026
20 of 21 checks passed
@paudley
paudley deleted the fix/cutover-exec-stack-recursion branch July 7, 2026 02:13

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request refactors Codex hook probe validation to use more specific validation helpers, simplifies hook CLI exit code logic to consistently return a blocked exit code, and updates associated tests. Additionally, it fixes a false positive in the managed lint tests by only inspecting targets after the "--" separator, and scrubs the execguard.EnvStack environment variable during cutover verification to prevent recursive self-blocking. There are no review comments, so no further feedback is provided.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

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