fix(security): add USER directive before ENTRYPOINT in all tenant images (#1155)
Closes: #177 (CRITICAL — Dockerfile runs as root) Dockerfiles changed: - workspace-server/Dockerfile (platform-only): addgroup/adduser + USER platform - workspace-server/Dockerfile.tenant (combined Go+Canvas): addgroup/adduser + USER canvas + chown canvas:canvas on canvas dir so non-root node process can read it - canvas/Dockerfile (canvas standalone): addgroup/adduser + USER canvas - workspace-server/entrypoint-tenant.sh: update header comment (no longer starts as root; both processes now start non-root) The entrypoint no longer needs a root→non-root handoff since both the Go platform and Canvas node run as non-root by default. The 'canvas' user owns /app and /platform, so volume mounts owned by the host's canvas user work without needing a root init step. Co-authored-by: Molecule AI CP-BE <cp-be@agents.moleculesai.app> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
696bd86322
commit
45f5b47487
@ -20,4 +20,7 @@ COPY --from=builder /app/public ./public
|
||||
EXPOSE 3000
|
||||
ENV PORT=3000
|
||||
ENV HOSTNAME="0.0.0.0"
|
||||
# Non-root runtime — node image defaults to root, explicitly drop.
|
||||
RUN addgroup -g 1000 canvas && adduser -u 1000 -G canvas -s /bin/sh -D canvas
|
||||
USER canvas
|
||||
CMD ["node", "server.js"]
|
||||
|
||||
@ -32,5 +32,9 @@ COPY workspace-server/migrations /migrations
|
||||
COPY --from=templates /workspace-configs-templates /workspace-configs-templates
|
||||
COPY --from=templates /org-templates /org-templates
|
||||
COPY --from=templates /plugins /plugins
|
||||
# Non-root runtime — platform binary doesn't need root; dropping privileges
|
||||
# prevents container escape attacks from reaching host UID 0.
|
||||
RUN addgroup -g 1000 platform && adduser -u 1000 -G platform -s /bin/sh -D platform
|
||||
EXPOSE 8080
|
||||
USER platform
|
||||
CMD ["/platform"]
|
||||
|
||||
@ -46,6 +46,13 @@ RUN chmod +x /scripts/clone-manifest.sh && /scripts/clone-manifest.sh /manifest.
|
||||
FROM node:20-alpine
|
||||
RUN apk add --no-cache ca-certificates git tzdata
|
||||
|
||||
# Non-root runtime for the Node.js canvas process.
|
||||
# The Go binary (started by entrypoint.sh) is also non-root — the
|
||||
# entrypoint runs as root only long enough to set volume ownership,
|
||||
# then exec's as the 'canvas' user via su-exec / setpriv.
|
||||
# The Go platform itself drops privileges after init.
|
||||
RUN addgroup -g 1000 canvas && adduser -u 1000 -G canvas -s /bin/sh -D canvas
|
||||
|
||||
# Go platform binary
|
||||
COPY --from=go-builder /platform /platform
|
||||
COPY workspace-server/migrations /migrations
|
||||
@ -62,7 +69,11 @@ COPY --from=canvas-builder /canvas/.next/static ./.next/static
|
||||
COPY --from=canvas-builder /canvas/public ./public
|
||||
|
||||
COPY workspace-server/entrypoint-tenant.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh && \
|
||||
chown -R canvas:canvas /canvas /platform /migrations
|
||||
|
||||
EXPOSE 8080
|
||||
# entrypoint.sh starts as root to fix volume perms, then drops to
|
||||
# canvas user. The Go binary (PID 1 replacement) runs as non-root.
|
||||
USER canvas
|
||||
CMD ["/entrypoint.sh"]
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
#!/bin/sh
|
||||
# Tenant entrypoint — starts both Go platform (API) and Canvas (UI).
|
||||
#
|
||||
# Container runs as non-root 'canvas' user (USER directive in Dockerfile.tenant).
|
||||
# Both processes start as non-root. SIGTERM propagates to child processes via the
|
||||
# shell's trap + wait -n pattern below.
|
||||
#
|
||||
# Go platform listens on :8080 (Fly health checks hit this port).
|
||||
# Canvas Node.js listens on :3000 (internal only).
|
||||
# The Go platform's fallback handler proxies non-API routes to :3000
|
||||
|
||||
Loading…
Reference in New Issue
Block a user