Skip to content

Commit de8882d

Browse files
CopilotMossaka
andcommitted
fix: eliminate nested bash layer in chroot command execution
Docker CMD passes commands as ['/bin/bash', '-c', 'command_string']. Previously, this was written to the chroot script file via printf '%q', creating an extra bash -c wrapper. This caused /proc/self/exe to resolve as /bin/bash for runtimes like Java and .NET that check their process identity. Now the command string is written directly when the standard bash -c pattern is detected. Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
1 parent 9a40e46 commit de8882d

File tree

2 files changed

+17
-2
lines changed

2 files changed

+17
-2
lines changed

containers/agent/entrypoint.sh

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,22 @@ AWFEOF
345345
fi
346346
fi
347347
# Append the actual command arguments
348-
printf '%q ' "$@" >> "/host${SCRIPT_FILE}"
349-
echo "" >> "/host${SCRIPT_FILE}"
348+
# Docker CMD passes commands as ['/bin/bash', '-c', 'command_string'].
349+
# Instead of writing the full [bash, -c, cmd] via printf '%q' (which creates
350+
# a nested bash -c layer), extract the command string and write it directly.
351+
# This eliminates an extra bash process layer that causes /proc/self/exe to
352+
# resolve as /bin/bash for runtimes like Java and .NET that check their own
353+
# process identity via /proc/self/exe.
354+
# Trust assumption: $3 comes from Docker CMD set by docker-manager.ts using
355+
# the user's own --allow-domains command. No additional sanitization needed.
356+
# We use $# -eq 3 (not -ge 3) intentionally: extra args beyond the command
357+
# string indicate a non-standard invocation that should fall back to printf.
358+
if [ "$1" = "/bin/bash" ] && [ "$2" = "-c" ] && [ $# -eq 3 ] && [ -n "$3" ]; then
359+
printf '%s\n' "$3" >> "/host${SCRIPT_FILE}"
360+
else
361+
printf '%q ' "$@" >> "/host${SCRIPT_FILE}"
362+
echo "" >> "/host${SCRIPT_FILE}"
363+
fi
350364
chmod +x "/host${SCRIPT_FILE}"
351365

352366
# Execute inside chroot:

docs/chroot-mode.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ As of v0.13.13, chroot mode mounts a fresh container-scoped procfs at `/host/pro
9494
2. This requires `CAP_SYS_ADMIN` capability, which is granted during container startup
9595
3. The procfs is container-scoped, showing only container processes (not host processes)
9696
4. `CAP_SYS_ADMIN` is dropped via capsh before executing user commands
97+
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`
9798

9899
**Security implications:**
99100
- The mounted procfs only exposes container processes, not host processes

0 commit comments

Comments
 (0)