diff --git a/containers/agent/entrypoint.sh b/containers/agent/entrypoint.sh index 77a25f10..9a3ab69f 100644 --- a/containers/agent/entrypoint.sh +++ b/containers/agent/entrypoint.sh @@ -345,8 +345,22 @@ AWFEOF fi fi # Append the actual command arguments - printf '%q ' "$@" >> "/host${SCRIPT_FILE}" - echo "" >> "/host${SCRIPT_FILE}" + # Docker CMD passes commands as ['/bin/bash', '-c', 'command_string']. + # Instead of writing the full [bash, -c, cmd] via printf '%q' (which creates + # a nested bash -c layer), extract the command string and write it directly. + # This eliminates an extra bash process layer that causes /proc/self/exe to + # resolve as /bin/bash for runtimes like Java and .NET that check their own + # process identity via /proc/self/exe. + # Trust assumption: $3 comes from Docker CMD set by docker-manager.ts using + # the user's own --allow-domains command. No additional sanitization needed. + # We use $# -eq 3 (not -ge 3) intentionally: extra args beyond the command + # string indicate a non-standard invocation that should fall back to printf. + if [ "$1" = "/bin/bash" ] && [ "$2" = "-c" ] && [ $# -eq 3 ] && [ -n "$3" ]; then + printf '%s\n' "$3" >> "/host${SCRIPT_FILE}" + else + printf '%q ' "$@" >> "/host${SCRIPT_FILE}" + echo "" >> "/host${SCRIPT_FILE}" + fi chmod +x "/host${SCRIPT_FILE}" # Execute inside chroot: diff --git a/docs/chroot-mode.md b/docs/chroot-mode.md index 851943bf..39c019f1 100644 --- a/docs/chroot-mode.md +++ b/docs/chroot-mode.md @@ -94,6 +94,7 @@ As of v0.13.13, chroot mode mounts a fresh container-scoped procfs at `/host/pro 2. This requires `CAP_SYS_ADMIN` capability, which is granted during container startup 3. The procfs is container-scoped, showing only container processes (not host processes) 4. `CAP_SYS_ADMIN` is dropped via capsh before executing user commands +5. The command script writes the user command directly (not wrapped in an extra `bash -c` layer), ensuring runtimes see their own binary via `/proc/self/exe` instead of `/bin/bash` **Security implications:** - The mounted procfs only exposes container processes, not host processes