From 469b00e9bbbf9f6064b199235bf86cae510d29d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20H=C3=B6fer?= Date: Thu, 8 Oct 2026 14:24:50 +0200 Subject: [PATCH] fix(agent): run sandbox commands directly instead of via node's entrypoint The default sandbox image inherited the node base image's entrypoint, which runs any command it can't find as a Node script. A misspelled agent (`agent run -- claude.`) failed with "Error: Cannot find module '/workspace/claude.'". The image now clears the entrypoint, so the command is exec'd directly and a typo fails with "exec claude. failed: No such file or directory" (exit 127). Every command the image runs is a real executable: the agent, the network holder's `sleep`, and `agent docker shell`, which already sets its own entrypoint. Existing installs keep the old image until it is rebuilt with `stashbase agent docker build --force`. --- docker/agent-sandbox/Dockerfile | 8 ++++++++ src/handlers/run/docker_sandbox.rs | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/docker/agent-sandbox/Dockerfile b/docker/agent-sandbox/Dockerfile index df0dfe3b..565bb08a 100644 --- a/docker/agent-sandbox/Dockerfile +++ b/docker/agent-sandbox/Dockerfile @@ -92,3 +92,11 @@ ENV DISABLE_AUTOUPDATER=1 # same image — the actual agent container never runs iptables itself and # holds no networking capabilities at all. WORKDIR /workspace + +# The node base image's entrypoint runs any command it can't find as a Node +# script, so a misspelled agent (`-- claude.`) failed with "Cannot find +# module '/workspace/claude.'". Every command this image runs is a real +# executable (the agent, the netns holder's `sleep`, `agent docker shell`'s +# bash), so run them directly: a typo now fails with Docker's own +# "executable file not found in $PATH". +ENTRYPOINT [] diff --git a/src/handlers/run/docker_sandbox.rs b/src/handlers/run/docker_sandbox.rs index 131e0bd6..99b59161 100644 --- a/src/handlers/run/docker_sandbox.rs +++ b/src/handlers/run/docker_sandbox.rs @@ -1568,6 +1568,13 @@ mod tests { assert!(SANDBOX_DOCKERFILE.contains("FROM")); } + #[test] + fn sandbox_dockerfile_clears_the_node_base_entrypoint() { + assert!(SANDBOX_DOCKERFILE + .lines() + .any(|line| line.trim() == "ENTRYPOINT []")); + } + #[test] fn agent_image_source_defaults_when_neither_field_is_set() { assert_eq!(