agentscope-ai / agentscope-ai/agentscope-java

[Bug]: DockerSandbox corrupts complex sh -c commands on Windows

オープン
#2,135 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る
area/harness bug
主要言語
Java
スター
5.6k
フォーク
1.3k
平均マージ
4日 12時間
マージ済み PR(30日)
77

説明

## Summary

On a Windows host, `DockerSandbox#doExec` passes the full shell program as the last argument of:

```text
docker exec -w sh -c
```

Commands containing command substitution and embedded quotes can be corrupted while crossing Java `ProcessBuilder` -> `docker.exe` -> container `sh -c`. This currently makes the standard Harness `write_file` path fail even for a tiny new file.

This is related to #1560 (large file content embedded in the command line), but the reproduction here is only a short preflight command and fails because of quoting, not command length.

## Environment

- Windows host
- Java 17
- Docker Desktop 29.2.0
- current `main` / AgentScope Java 2.0 Harness
- image: `ubuntu:24.04`

## Minimal reproduction

Create and start an official Docker sandbox, then attach it to `SandboxBackedFilesystem` and call:

```java
SandboxBackedFilesystem filesystem = new SandboxBackedFilesystem();
filesystem.setSandbox(sandbox);
WriteResult result = filesystem.write(
runtimeContext,
"filesystem-contract.txt",
"jcode-filesystem-contract");
```

Expected:

```text
WriteResult.success
```

Actual:

```text
Failed to write file 'filesystem-contract.txt'
```

Calling the exact preflight command directly exposes the hidden error:

```java
sandbox.exec(
runtimeContext,
"if [ -e 'filesystem-contract.txt' ]; then echo 'EXISTS'; exit 1; fi; "
+ "mkdir -p \"$(dirname 'filesystem-contract.txt')\" 2>&1",
60);
```

Actual container shell error:

```text
Command exited with code 2: 'filesystem-contract.txt') 2>&1: 1: Syntax error: end of file unexpected (expecting ")")
```

The same shell program succeeds when invoked manually inside the same `ubuntu:24.04` image.

## Source path

`BaseSandboxFilesystem.write()` creates the preflight:

```java
String checkCmd =
"if [ -e " + escapedPath + " ]; then echo 'EXISTS'; exit 1; fi; "
+ "mkdir -p \"$(dirname " + escapedPath + ")\" 2>&1";
```

`DockerSandbox#doExec()` then appends that program directly as a Windows process argument:

```java
cmd.add("sh");
cmd.add("-c");
cmd.add(command);
new ProcessBuilder(cmd).start();
```

Docker events show the `sh -c` command reaching the container with damaged quoting. `BaseSandboxFilesystem.write()` also replaces the real preflight output with the generic `Failed to write file` message, which initially hides the cause.

## Impact

- Standard Harness `write_file` fails for Docker sandbox on Windows.
- `edit_file` and other complex shell-backed filesystem operations may be affected.
- Redis/MySQL cross-replica sandbox recovery cannot complete because the writer phase cannot create the workspace file.
- The failure is unrelated to Redis, snapshot persistence, or Windows host path mapping; it also reproduces in a standalone official Docker sandbox without distributed storage.

## Suggested direction

Avoid transporting a shell program as a complex `docker.exe` command-line argument on Windows. A platform-independent approach is to stream the program through stdin, for example:

```text
docker exec -i -w sh -s
```

and write the program to process stdin. This direction also aligns with #1560 and avoids both quoting corruption and OS command-line length limits.

Separately, preserve `checkResult.output()` and exit code in the `BaseSandboxFilesystem.write()` preflight failure so future backend failures remain diagnosable.

I can prepare a focused PR with Windows/Linux tests if maintainers agree with the stdin execution direction.

コントリビューションガイド

コントリビューションガイドを開く

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。