fix: resolve root cause of user switching failure in Docker
This fixes the fundamental issue causing persistent test failures. Root Cause: - The entrypoint script's user switching was broken - Used 'exec $*' which fails when no arguments provided - Used 'printf %q' which doesn't exist in Alpine Linux - User switching wasn't actually working properly Fixes: 1. Added su-exec package to Dockerfile - Proper tool for switching users in containers - Handles signal propagation correctly - No intermediate shell process 2. Rewrote user switching logic - Uses su-exec with fallback to su - Fixed command injection vulnerability in su fallback - Properly handles case when no arguments provided - Exports environment variables before switching 3. Added security improvements - Restricted permissions on AUTH_TOKEN_FILE - Added comments explaining su-exec benefits This explains why tests kept failing - we were testing around a broken implementation rather than fixing the actual broken code.
This commit is contained in:
@@ -26,7 +26,7 @@ FROM node:22-alpine AS runtime
|
||||
WORKDIR /app
|
||||
|
||||
# Install only essential runtime tools
|
||||
RUN apk add --no-cache curl && \
|
||||
RUN apk add --no-cache curl su-exec && \
|
||||
rm -rf /var/cache/apk/*
|
||||
|
||||
# Copy runtime-only package.json
|
||||
|
||||
@@ -94,8 +94,34 @@ if [ "$(id -u)" = "0" ]; then
|
||||
chown -R nodejs:nodejs /app/data
|
||||
fi
|
||||
# Switch to nodejs user with proper exec chain for signal propagation
|
||||
# Preserve environment variables when switching user
|
||||
exec su -s /bin/sh nodejs -c "export MCP_MODE='$MCP_MODE'; export NODE_DB_PATH='$NODE_DB_PATH'; export AUTH_TOKEN='$AUTH_TOKEN'; export AUTH_TOKEN_FILE='$AUTH_TOKEN_FILE'; exec $*"
|
||||
# Build the command to execute
|
||||
if [ $# -eq 0 ]; then
|
||||
# No arguments provided, use default CMD from Dockerfile
|
||||
set -- node /app/dist/mcp/index.js
|
||||
fi
|
||||
# Export all needed environment variables
|
||||
export MCP_MODE="$MCP_MODE"
|
||||
export NODE_DB_PATH="$NODE_DB_PATH"
|
||||
export AUTH_TOKEN="$AUTH_TOKEN"
|
||||
export AUTH_TOKEN_FILE="$AUTH_TOKEN_FILE"
|
||||
|
||||
# Ensure AUTH_TOKEN_FILE has restricted permissions for security
|
||||
if [ -n "$AUTH_TOKEN_FILE" ] && [ -f "$AUTH_TOKEN_FILE" ]; then
|
||||
chmod 600 "$AUTH_TOKEN_FILE" 2>/dev/null || true
|
||||
chown nodejs:nodejs "$AUTH_TOKEN_FILE" 2>/dev/null || true
|
||||
fi
|
||||
# Use exec with su-exec for proper signal handling (Alpine Linux)
|
||||
# su-exec advantages:
|
||||
# - Proper signal forwarding (critical for container shutdown)
|
||||
# - No intermediate shell process
|
||||
# - Designed for privilege dropping in containers
|
||||
if command -v su-exec >/dev/null 2>&1; then
|
||||
exec su-exec nodejs "$@"
|
||||
else
|
||||
# Fallback to su with preserved environment
|
||||
# Use safer approach to prevent command injection
|
||||
exec su -p nodejs -s /bin/sh -c 'exec "$0" "$@"' -- sh -c 'exec "$@"' -- "$@"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Handle special commands
|
||||
@@ -130,5 +156,10 @@ if [ "$MCP_MODE" = "stdio" ]; then
|
||||
fi
|
||||
else
|
||||
# HTTP mode or other
|
||||
if [ $# -eq 0 ]; then
|
||||
# No arguments provided, use default
|
||||
exec node /app/dist/mcp/index.js
|
||||
else
|
||||
exec "$@"
|
||||
fi
|
||||
fi
|
||||
Reference in New Issue
Block a user