monad-developers / monad-developers/ultrafuzz

Provider-home env vars are neutralized to "" instead of unset, so the Claude CLI falls back to cwd and writes session state into the agent worktree

Open
#986 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
85
Forks
18
Avg merge
11h 10m
Merged PRs (30d)
194

Description

Summary

workflowControlChildEnvironment neutralizes BUILT_IN_PROVIDER_HOME_ENVIRONMENT_VARIABLES (including CLAUDE_CONFIG_DIR) by assigning the empty string:

const child: Record<string, string> = Object.fromEntries(
  [
    ...CONTROLLER_ONLY_ENVIRONMENT_VARIABLES,
    ...BUILT_IN_PROVIDER_HOME_ENVIRONMENT_VARIABLES,
    ...providerCredentialEnvironmentVariables(source)
  ].map((name) => [name, ""])
);

An empty value is not equivalent to an unset variable. Claude Code treats an empty CLAUDE_CONFIG_DIR as absent and falls back to the current working directory for its config dir, rather than to ~/.claude.

Impact

When an agent runs without a forwarded config directory, the CLI writes its session state into the agent's own git worktree:

projects/<munged-cwd>/<session-id>.jsonl
projects/<munged-cwd>/<session-id>/tool-results/<id>.txt

Those files become part of the workspace patch. They are agent session transcripts, so this also means conversation state is written into a tree that is diffed, snapshotted, and handed to downstream nodes.

Combined with the 128-character WORKSPACE_PATCH_SEGMENT cap (filed separately), <munged-cwd> is the absolute worktree path with separators replaced, so the run fails non-deterministically depending on path length:

✗ verify:setup-foundry (attempt 1): workspace patch file path contains an unsafe path segment
✗ Run failed: Task failed: verify:setup-foundry

Two runs of the same project, differing only in the length of the run id, produced a 123-character segment (passed) and a 130-character segment (failed).

Suggested direction

Neutralizing by assignment is the right intent, but for variables whose absence is meaningful the child environment should omit the key rather than set it to "". Worth auditing the other entries in BUILT_IN_PROVIDER_HOME_ENVIRONMENT_VARIABLES (CODEX_HOME, KIMI_CODE_HOME, KIMI_SHARE_DIR) for the same CLI-dependent behavior.

I have not attempted a fix: this is the credential/environment isolation boundary and I could not validate a change to it across all providers.

Notes

  • Reproduced on darwin/arm64 with ClaudeAgent + auth = "subscription".
  • Not macOS-specific in principle — the empty-vs-unset distinction applies anywhere.
  • Encountered while making the config directory conditional; the correct resolution there was operational (register the config dir once via CLAUDE_CONFIG_DIR=<dir> claude + /login, since Claude Code scopes the subscription credential per config directory). But the empty-string neutralization remains a latent trap for any code path that legitimately omits a provider home.

🤖 Generated with Claude Code

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at workflowControlChildEnvironment and inspect how BUILT_IN_PROVIDER_HOME_ENVIRONMENT_VARIABLES are assembled into the child environment. Compare empty-string neutralization with omission for CLAUDE_CONFIG_DIR, then audit CODEX_HOME, KIMI_CODE_HOME, and KIMI_SHARE_DIR. Done means the reported ClaudeAgent scenario no longer writes session state into the agent worktree while credential isolation remains intact.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
devtools, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.