Skip to content

fix(agent-isolation): don't replace the caller's shell when agent-iso.sh is sourced - #1121

Merged
potiuk merged 1 commit into
apache:mainfrom
potiuk:fix/agent-iso-no-exec-when-sourced
Aug 29, 2026
Merged

fix(agent-isolation): don't replace the caller's shell when agent-iso.sh is sourced#1121
potiuk merged 1 commit into
apache:mainfrom
potiuk:fix/agent-iso-no-exec-when-sourced

Conversation

@potiuk

@potiuk potiuk commented Aug 29, 2026

Copy link
Copy Markdown
Member

Summary

  • agent_iso_run in tools/agent-isolation/agent-iso.sh ended with an unconditional
    exec env -i … "$agent_bin". That is right for bash agent-iso.sh …, where the process
    exists only to become the agent — but wrong on the sourced path, the documented rc-file
    setup where claude-iso / agent-iso are shell functions. There the current process is the
    user's own interactive shell, so exec replaced it: quitting the agent closed the terminal,
    and a launch that failed (lost exec bit, bad interpreter, binary swapped mid-upgrade) took
    the shell down with it.
  • The sourced/direct branch now records which mode the script loaded in; agent_iso_run uses
    that to run the agent as a child and return its exit status when sourced, and to keep
    execing when executed directly.

Type of change

  • Python package (tools/*/ with pyproject.toml)
  • Cross-cutting (RFC, AGENTS.md, sandbox, privacy-LLM)

Test plan

  • prek run --all-files passes
  • uv run pytest passes in tools/agent-isolation (88 passed)
  • New TestSourcedDoesNotReplaceTheShell covers: the shell surviving the agent, the agent's
    exit status reaching the shell, the shell surviving a failed launch (a missing-interpreter
    shebang — previously fatal to the shell), the named claude-iso launcher, and a guard that
    direct exec still execs.
    The first four fail against the pre-fix script — verified by restoring it and re-running.

RFC-AI-0004 compliance

  • Sandbox — no new host access; the change only affects which process the agent replaces.

Notes for reviewers

  • The direct-exec path deliberately keeps exec. That process exists only to become the agent,
    so replacing it is correct and saves a process; only the sourced path changed.
  • The exit 1 calls at the bottom of the script were already confined to the direct-exec
    branch, and the sourced entry points already used returnexec was the only remaining
    path that could take the parent shell down.
  • The other ten scripts under tools/agent-isolation/ are hooks and shims that are always
    executed, never sourced, so none needed the same treatment.
  • Mode detection reuses the existing [[ "${BASH_SOURCE[0]}" != "${0}" ]] check. Under zsh
    BASH_SOURCE is unset, which lands on the sourced branch — the correct answer there, since
    direct execution always goes through the bash shebang.

@potiuk
potiuk force-pushed the fix/agent-iso-no-exec-when-sourced branch from 4975958 to 74ea4cc Compare August 29, 2026 17:33
`agent_iso_run` ended with an unconditional `exec env -i … "$agent_bin"`.
That is right for `bash agent-iso.sh …`, where the process exists only to
become the agent. It is wrong on the sourced path — the documented rc-file
setup, where `claude-iso` / `agent-iso` are shell functions — because there
the current process is the user's own interactive shell. `exec` replaced
it: quitting the agent closed the terminal, and a launch that failed (lost
exec bit, bad interpreter, binary swapped mid-upgrade) took the shell down
with it.

The sourced/direct branch now records which mode the script loaded in, and
`agent_iso_run` uses it to pick the launch: sourced runs the agent as a
child and returns its exit status, direct exec still `exec`s. The `exit 1`
calls were already confined to the direct-exec branch and the sourced entry
points already used `return`, so `exec` was the only parent-killing path.

The other scripts under tools/agent-isolation/ are hooks and shims that are
always executed, never sourced, so none of them needed the same treatment.

Adds TestSourcedDoesNotReplaceTheShell covering shell survival, exit-status
propagation, survival of a failed launch, the named `claude-iso` launcher,
and a guard that direct exec still `exec`s. The first four fail against the
previous script.
@potiuk
potiuk force-pushed the fix/agent-iso-no-exec-when-sourced branch from 74ea4cc to 7f7398e Compare August 29, 2026 17:47
@potiuk
potiuk merged commit 9fa7c2f into apache:main Aug 29, 2026
9 checks passed
@potiuk
potiuk deleted the fix/agent-iso-no-exec-when-sourced branch August 29, 2026 18:12
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