@@ -397,6 +397,45 @@ unset_sensitive_tokens() {
397397 done
398398}
399399
400+ # Run a command with signal handling, one-shot token protection, and clean exit.
401+ # Usage: run_agent_with_token_protection <command> [args...]
402+ # The command is launched in the background so that sensitive tokens can be unset
403+ # from the parent shell's environment once the agent has had time to cache them.
404+ run_agent_with_token_protection () {
405+ # Setup signal handler to forward signals to agent process and perform cleanup
406+ cleanup_and_exit () {
407+ if [ -n " $AGENT_PID " ]; then
408+ kill -TERM " $AGENT_PID " 2> /dev/null || true
409+ wait " $AGENT_PID " 2> /dev/null || true
410+ fi
411+ exit 143 # Standard exit code for SIGTERM
412+ }
413+ trap cleanup_and_exit TERM INT
414+
415+ # SECURITY: Run agent command in background, then unset tokens from parent shell
416+ # This prevents tokens from being accessible via /proc/1/environ after agent starts
417+ # The one-shot-token library caches tokens in the agent process, so agent can still read them
418+ " $@ " &
419+ AGENT_PID=$!
420+
421+ # Wait for agent to initialize and cache tokens (up to 1 second)
422+ # The one-shot-token LD_PRELOAD library caches tokens in ~100ms during process init.
423+ # Poll every 100ms so fast commands (e.g. 'echo ok') don't pay the full wait.
424+ for _i in 1 2 3 4 5 6 7 8 9 10; do
425+ kill -0 " $AGENT_PID " 2> /dev/null || break
426+ sleep 0.1
427+ done
428+
429+ # Unset all sensitive tokens from parent shell environment
430+ unset_sensitive_tokens
431+
432+ # Wait for agent command to complete and capture its exit code
433+ wait $AGENT_PID
434+ EXIT_CODE=$?
435+ trap - TERM INT
436+ exit $EXIT_CODE
437+ }
438+
400439echo " [entrypoint] Switching to awfuser (UID: $( id -u awfuser) , GID: $( id -g awfuser) )"
401440echo " [entrypoint] Executing command: $@ "
402441echo " "
@@ -848,43 +887,12 @@ AWFEOF
848887 LD_PRELOAD_CMD=" export LD_PRELOAD=${ONE_SHOT_TOKEN_LIB} ;"
849888 fi
850889
851- # Setup signal handler to forward signals to agent process and perform cleanup
852- cleanup_and_exit () {
853- if [ -n " $AGENT_PID " ]; then
854- kill -TERM " $AGENT_PID " 2> /dev/null || true
855- wait " $AGENT_PID " 2> /dev/null || true
856- fi
857- exit 143 # Standard exit code for SIGTERM
858- }
859- trap cleanup_and_exit TERM INT
860-
861- # SECURITY: Run agent command in background, then unset tokens from parent shell
862- # This prevents tokens from being accessible via /proc/1/environ after agent starts
863- # The one-shot-token library caches tokens in the agent process, so agent can still read them
864- chroot /host /bin/bash -c "
890+ run_agent_with_token_protection chroot /host /bin/bash -c "
865891 cd '${CHROOT_WORKDIR} ' 2>/dev/null || cd /
866892 trap '${CLEANUP_CMD} ' EXIT
867893 ${LD_PRELOAD_CMD}
868894 exec capsh --drop=${CAPS_TO_DROP} --user=${HOST_USER} -- -c 'exec ${SCRIPT_FILE} '
869- " &
870- AGENT_PID=$!
871-
872- # Wait for agent to initialize and cache tokens (up to 1 second)
873- # The one-shot-token LD_PRELOAD library caches tokens in ~100ms during process init.
874- # Poll every 100ms so fast commands (e.g. 'echo ok') don't pay the full wait.
875- for _i in 1 2 3 4 5 6 7 8 9 10; do
876- kill -0 " $AGENT_PID " 2> /dev/null || break
877- sleep 0.1
878- done
879-
880- # Unset all sensitive tokens from parent shell environment
881- unset_sensitive_tokens
882-
883- # Wait for agent command to complete and capture its exit code
884- wait $AGENT_PID
885- EXIT_CODE=$?
886- trap - TERM INT
887- exit $EXIT_CODE
895+ "
888896else
889897 # Original behavior - run in container filesystem
890898 # Drop capabilities and privileges, then execute the user command
@@ -915,41 +923,10 @@ else
915923 # unset from the environment so /proc/self/environ is cleared
916924 export LD_PRELOAD=/usr/local/lib/one-shot-token.so
917925
918- # Setup signal handler to forward signals to agent process and perform cleanup
919- cleanup_and_exit () {
920- if [ -n " $AGENT_PID " ]; then
921- kill -TERM " $AGENT_PID " 2> /dev/null || true
922- wait " $AGENT_PID " 2> /dev/null || true
923- fi
924- exit 143 # Standard exit code for SIGTERM
925- }
926- trap cleanup_and_exit TERM INT
927-
928- # SECURITY: Run agent command in background, then unset tokens from parent shell
929- # This prevents tokens from being accessible via /proc/1/environ after agent starts
930- # The one-shot-token library caches tokens in the agent process, so agent can still read them
931926 if [ -n " $CAPS_TO_DROP " ]; then
932- capsh --drop=$CAPS_TO_DROP -- -c " exec gosu awfuser $( printf ' %q ' " $@ " ) " &
927+ run_agent_with_token_protection capsh --drop=$CAPS_TO_DROP -- -c " exec gosu awfuser $( printf ' %q ' " $@ " ) "
933928 else
934929 # No capabilities to drop - just switch to unprivileged user
935- gosu awfuser " $@ " &
930+ run_agent_with_token_protection gosu awfuser " $@ "
936931 fi
937- AGENT_PID=$!
938-
939- # Wait for agent to initialize and cache tokens (up to 1 second)
940- # The one-shot-token LD_PRELOAD library caches tokens in ~100ms during process init.
941- # Poll every 100ms so fast commands (e.g. 'echo ok') don't pay the full wait.
942- for _i in 1 2 3 4 5 6 7 8 9 10; do
943- kill -0 " $AGENT_PID " 2> /dev/null || break
944- sleep 0.1
945- done
946-
947- # Unset all sensitive tokens from parent shell environment
948- unset_sensitive_tokens
949-
950- # Wait for agent command to complete and capture its exit code
951- wait $AGENT_PID
952- EXIT_CODE=$?
953- trap - TERM INT
954- exit $EXIT_CODE
955932fi
0 commit comments