agentscope-ai / agentscope-ai/agentscope-java
[Bug]: DockerSandbox corrupts complex sh -c commands on Windows
- 主要语言
- Java
- 星标
- 5.6k
- 派生
- 1.3k
- 平均合并
- 4 天 12 小时
- 30 天内合并 PR
- 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 还没有评估数据。