Skip to content

fix: replace REACH_SESSION in harness environments rather than appending it - #16

Merged
bojieli merged 1 commit into
mainfrom
fix-duplicate-reach-session-env
Aug 22, 2026
Merged

fix: replace REACH_SESSION in harness environments rather than appending it#16
bojieli merged 1 commit into
mainfrom
fix-duplicate-reach-session-env

Conversation

@bojieli

@bojieli bojieli commented Aug 22, 2026

Copy link
Copy Markdown
Owner

What this changes

Every harness launcher built its child environment as os.Environ() plus "REACH_SESSION=<name>". When the operator's shell already exported REACH_SESSION — the documented way to bind a shell to a session — the child received the key twice, and which of the two a program reads is not defined.

The failure that matters: the shim would resolve a different session than the launch had just named on stderr, so the agent's commands would run on that session's target while every message said this one. That is silent wrong-target execution, arrived at through reach's own environment handling.

replaceEnv already existed for exactly this reason and was already used for CODEX_HOME and HOME. It is now used for REACH_SESSION in every launcher, and for CLAUDE_CODE_SHELL_PREFIX, which had the same shape.

The harness seam probes had the same bug with worse consequences: baseProbeEnv and claudeCodeEnv copy the current environment and append the throwaway probe session, so an inherited REACH_SESSION could win and route the probe's canary through the operator's real session. The probe would then return a verdict about a seam it never exercised — the one thing a fail-closed guard must never do. Both now strip an inherited value before setting their own.

Checklist

  • make check and make lint pass
  • make integration passes, if this touches transports or file operations — not run; this touches neither
  • Comments explain why where the code looks odd

If this touches a harness adapter:

  • A conformance test covers the seam, and fails when the seam changes shape — no seam shape changed; this is environment construction on the launcher side
  • docs/RESEARCH.md records what was observed — no new harness observation
  • Anything not verified is written down as unverified rather than implied to work

Verified by unit tests and make check only: reproducing the duplicate-key path end to end needs a real harness and a target, and was not run here.

🤖 Generated with Claude Code

https://claude.ai/code/session_018WMXbmmHmEkyWWRc72uvPW

…ing it

Every launcher built its child environment as os.Environ() plus
"REACH_SESSION=<name>". When the operator's shell already exported
REACH_SESSION — the documented way to bind a shell to a session — the
child received the key twice, and which of the two a program reads is
not defined. The shim would then resolve a different session than the
launch had just named on stderr, and the agent's commands would run on
that session's target while every message said this one.

replaceEnv already existed for exactly this reason and was already used
for CODEX_HOME and HOME; it is now used for REACH_SESSION as well, and
for CLAUDE_CODE_SHELL_PREFIX, which had the same shape.

The harness seam probes had the same bug with worse consequences: they
copy the current environment and append the throwaway probe session, so
an inherited REACH_SESSION could win and route the probe's canary
through the operator's real session. The probe would then report a
verdict about a seam it never exercised, which is the one thing a
fail-closed guard must never do. baseProbeEnv and claudeCodeEnv now
strip an inherited value before setting their own.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018WMXbmmHmEkyWWRc72uvPW
@bojieli
bojieli force-pushed the fix-duplicate-reach-session-env branch from 376ca98 to 86383b3 Compare August 22, 2026 04:44
@bojieli
bojieli merged commit 8bdd8f6 into main Aug 22, 2026
23 checks passed
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