Skip to content

fix: preserve sandbox write payload stdin#43876

Merged
altaywtf merged 2 commits intoopenclaw:mainfrom
glitch418x:UINAF-104-sandbox-write-bridge
Mar 12, 2026
Merged

fix: preserve sandbox write payload stdin#43876
altaywtf merged 2 commits intoopenclaw:mainfrom
glitch418x:UINAF-104-sandbox-write-bridge

Conversation

@glitch418x
Copy link
Contributor

@glitch418x glitch418x commented Mar 12, 2026

Summary

  • Sandbox write could report success while creating a zero-byte file.
  • Root cause: the pinned mutation helper used stdin for both the Python source and the file payload.
  • Fix: send the helper source over fd 3 and keep stdin exclusively for write bytes.
  • Added regression coverage for the shell-wrapped pinned write path.

Change Type

  • Bug fix

Scope

  • Skills / tool execution

Linked Issue/PR

  • Related internal tracking issue

User-visible / Behavior Changes

  • Sandboxed built-in write now preserves payload bytes instead of creating empty files while reporting success.

Security Impact

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: macOS arm64
  • Runtime/container: local gateway from source + Docker sandbox
  • Integration/channel: sandboxed Telegram chaos session

Steps

  1. In a sandboxed agent session, call built-in write with a small payload.
  2. Inspect the written file from container and host.
  3. Compare the tool success message with actual file contents.

Expected

  • The file contains the provided bytes.

Actual

  • The file existed but was 0 bytes while the tool reported success.

Evidence

  • Failing repro/log before + passing targeted tests after
  • Trace/log snippets

Human Verification

  • Verified the live repro produced a zero-byte file on both host and container.
  • Traced the helper launch path and confirmed stdin was being double-used.
  • Ran targeted tests after the fix:
    • ./node_modules/.bin/vitest run src/agents/sandbox/fs-bridge-mutation-helper.test.ts src/agents/sandbox/fs-bridge.shell.test.ts src/agents/sandbox/fs-bridge.anchored-ops.test.ts
  • Result: 23 tests passed.

Not verified in this PR branch:

  • a second live chaos-session repro after applying the patch in the running local gateway

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Failure Recovery

  • Revert this PR/commit.
  • Watch for any regressions in sandbox mutation helper execution or stdin handling.

Risks and Mitigations

  • Risk: fd 3 helper delivery could behave differently on some shells/platforms.
    • Mitigation: added focused regression coverage for the shell-wrapped write path and kept the change isolated to the helper launch string.

@openclaw-barnacle openclaw-barnacle bot added agents Agent runtime and tooling size: S labels Mar 12, 2026
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 12, 2026

Greptile Summary

This PR fixes a bug where the sandbox pinned write helper's Python script was consuming stdin via a here-document (python3 - "$@" <<'PY'), leaving no channel for the actual file payload bytes. The fix redirects the Python source to fd 3 (python3 /dev/fd/3 "$@" 3<<'PY'), freeing stdin (fd 0) for write_atomic to consume as the write payload. A focused regression test (runWritePlan) is added to prove the sh-wrapped path correctly delivers stdin bytes to the written file.

  • fs-bridge-mutation-helper.ts: buildPinnedMutationPlan now generates a 3<<'PY' heredoc so the Python source lands on fd 3 and sys.stdin.buffer in write_atomic is free to read the file payload.
  • fs-bridge-mutation-helper.test.ts: exports buildPinnedWritePlan for use in the new runWritePlan helper and adds a platform-gated regression test that exercises the full sh -c path with an input payload.
  • fs-bridge.shell.test.ts / fs-bridge.anchored-ops.test.ts: assertion strings updated to match the new script fragment.
  • No changes to argument positions — sys.argv[1] through sys.argv[5] map identically between the old python3 - and new python3 /dev/fd/3 invocation styles.

Confidence Score: 5/5

  • This PR is safe to merge — the change is minimal, well-reasoned, and covered by a targeted regression test.
  • The fix is technically sound: 3<<'PY' is valid POSIX sh, /dev/fd/3 is reliably available in the Linux Docker sandbox environment this code targets, and sys.argv positions are identical between the old python3 - and new python3 /dev/fd/3 invocation styles. The regression test directly exercises the broken path (stdin bytes through the sh-wrapped plan) and confirms the fix. All existing tests still pass and assertions in two other test files are correctly updated to match the new script fragment.
  • No files require special attention.

Last reviewed commit: fffcf38

@glitch418x glitch418x force-pushed the UINAF-104-sandbox-write-bridge branch from fffcf38 to b4e9422 Compare March 12, 2026 09:09
@altaywtf altaywtf self-assigned this Mar 12, 2026
@altaywtf altaywtf force-pushed the UINAF-104-sandbox-write-bridge branch from b4e9422 to d438cb8 Compare March 12, 2026 09:37
@altaywtf altaywtf force-pushed the UINAF-104-sandbox-write-bridge branch from d438cb8 to a10fd4b Compare March 12, 2026 09:42
@altaywtf altaywtf merged commit 8ea79b6 into openclaw:main Mar 12, 2026
12 checks passed
@altaywtf
Copy link
Member

Merged via squash.

Thanks @glitch418x!

lml2468 added a commit to lml2468/openclaw that referenced this pull request Mar 12, 2026
Defense-in-depth for openclaw#43858: even after the heredoc stdin fix (openclaw#43876),
a broken pipe or abort race could still deliver 0 bytes to the Python
write helper. Without this guard, run_write atomically replaces the
target file with a 0-byte temp file, silently destroying content.

Add an os.fstat check after write_stdin_to_fd: when the temp file is
empty and the target already exists, raise RuntimeError instead of
proceeding with os.replace. Creating new empty files is still allowed.

AI-assisted (Claude, fully tested)
GGzili pushed a commit to GGzili/moltbot that referenced this pull request Mar 12, 2026
Merged via squash.

Prepared head SHA: a10fd4b
Co-authored-by: glitch418x <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf
steipete pushed a commit to BruceMacD/openclaw that referenced this pull request Mar 13, 2026
Merged via squash.

Prepared head SHA: a10fd4b
Co-authored-by: glitch418x <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf
Interstellar-code pushed a commit to Interstellar-code/operator1 that referenced this pull request Mar 16, 2026
Merged via squash.

Prepared head SHA: a10fd4b
Co-authored-by: glitch418x <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

(cherry picked from commit 8ea79b6)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants