Context
Reported upstream in github/agentic-workflows#535. Enterprise customers using ARC self-hosted runners with Alpine-based DinD images (docker:dind) cannot run AWF because the one-shot-token.so library fails to load.
Problem
The one-shot-token.so LD_PRELOAD library is compiled from C against glibc (libc6-dev) in the agent container Dockerfile (containers/agent/Dockerfile). When entrypoint.sh copies it to /host/tmp/awf-lib/one-shot-token.so and sets LD_PRELOAD, the host process (running on Alpine/musl) fails with:
Error relocating /tmp/awf-lib/one-shot-token.so: __fprintf_chk: symbol not found
__fprintf_chk is a glibc-specific fortified I/O function with no musl equivalent. Alpine's gcompat / libc6-compat packages do not cover it.
Affected code path
containers/agent/Dockerfile — compiles one-shot-token.c with gcc -shared against glibc
containers/agent/entrypoint.sh — copies .so to /host/tmp/awf-lib/ and sets LD_PRELOAD
- Host process loads the
.so via LD_PRELOAD — fails on musl-based hosts
Potential Solutions
Option A: Statically link one-shot-token.so (Recommended)
Compile with -static or use musl-compatible build flags. Since the library only uses basic libc functions (getenv, setenv, unsetenv, dlsym), it can avoid glibc-specific fortified functions:
# Compile without fortification to avoid __fprintf_chk
gcc -shared -fPIC -fvisibility=hidden -O2 -Wall -s \
-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 \
-o /usr/local/lib/one-shot-token.so /tmp/one-shot-token.c -ldl -lpthread
This removes the dependency on __fprintf_chk while keeping the library dynamically loadable. The one-shot-token code is security-sensitive but simple — it only intercepts getenv() to provide one-shot access to API tokens.
Option B: Build a musl-compatible variant
Add a multi-stage build step that compiles a second .so using musl-gcc or an Alpine build stage. At runtime, detect the libc and load the appropriate variant.
Option C: Graceful degradation
If the .so fails to load, fall back to the non-LD_PRELOAD behavior (tokens remain in env). This is already partially implemented — entrypoint.sh checks if [ -f /usr/local/lib/one-shot-token.so ] — but the failure occurs at load time, not at the file check.
Add a runtime probe before committing to LD_PRELOAD:
if LD_PRELOAD=/host/tmp/awf-lib/one-shot-token.so /bin/true 2>/dev/null; then
ONE_SHOT_TOKEN_LIB="/tmp/awf-lib/one-shot-token.so"
else
echo "[WARN] one-shot-token.so incompatible with host libc, tokens will remain in env"
fi
Impact
Blocking enterprise ARC deployments on Alpine-based DinD runners. Option A is likely the simplest fix — just disable _FORTIFY_SOURCE in the gcc flags.
Context
Reported upstream in github/agentic-workflows#535. Enterprise customers using ARC self-hosted runners with Alpine-based DinD images (
docker:dind) cannot run AWF because theone-shot-token.solibrary fails to load.Problem
The
one-shot-token.soLD_PRELOAD library is compiled from C against glibc (libc6-dev) in the agent container Dockerfile (containers/agent/Dockerfile). Whenentrypoint.shcopies it to/host/tmp/awf-lib/one-shot-token.soand setsLD_PRELOAD, the host process (running on Alpine/musl) fails with:__fprintf_chkis a glibc-specific fortified I/O function with no musl equivalent. Alpine'sgcompat/libc6-compatpackages do not cover it.Affected code path
containers/agent/Dockerfile— compilesone-shot-token.cwithgcc -sharedagainst glibccontainers/agent/entrypoint.sh— copies.soto/host/tmp/awf-lib/and setsLD_PRELOAD.soviaLD_PRELOAD— fails on musl-based hostsPotential Solutions
Option A: Statically link one-shot-token.so (Recommended)
Compile with
-staticor use musl-compatible build flags. Since the library only uses basic libc functions (getenv,setenv,unsetenv,dlsym), it can avoid glibc-specific fortified functions:# Compile without fortification to avoid __fprintf_chk gcc -shared -fPIC -fvisibility=hidden -O2 -Wall -s \ -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 \ -o /usr/local/lib/one-shot-token.so /tmp/one-shot-token.c -ldl -lpthreadThis removes the dependency on
__fprintf_chkwhile keeping the library dynamically loadable. The one-shot-token code is security-sensitive but simple — it only interceptsgetenv()to provide one-shot access to API tokens.Option B: Build a musl-compatible variant
Add a multi-stage build step that compiles a second
.sousingmusl-gccor an Alpine build stage. At runtime, detect the libc and load the appropriate variant.Option C: Graceful degradation
If the
.sofails to load, fall back to the non-LD_PRELOAD behavior (tokens remain in env). This is already partially implemented —entrypoint.shchecksif [ -f /usr/local/lib/one-shot-token.so ]— but the failure occurs at load time, not at the file check.Add a runtime probe before committing to
LD_PRELOAD:Impact
Blocking enterprise ARC deployments on Alpine-based DinD runners. Option A is likely the simplest fix — just disable
_FORTIFY_SOURCEin the gcc flags.