Skip to content

Commit 12f3f2a

Browse files
committed
Harden runtime Dockerfile user and file permissions
1 parent a5c5d4b commit 12f3f2a

2 files changed

Lines changed: 49 additions & 31 deletions

File tree

bun.lock

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/core/src/docker/Dockerfile

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ ENV TZ=UTC
8282
ENV LANG=C.UTF-8
8383
ENV LC_ALL=C.UTF-8
8484

85+
# Runtime user identity (override at build time if host volume mapping needs it).
86+
# These are preferred IDs, not strict requirements:
87+
# - If OPENCODER_GID is already occupied, we create `opencoder` with the next free GID.
88+
# - If OPENCODER_UID is already occupied, we create `opencoder` with the next free UID.
89+
# This avoids collisions with base-image users (for example Ubuntu's default uid/gid 1000)
90+
# while still allowing operators to request specific IDs when available.
91+
ARG OPENCODER_UID=1000
92+
ARG OPENCODER_GID=1000
93+
8594
# -----------------------------------------------------------------------------
8695
# System Dependencies
8796
# -----------------------------------------------------------------------------
@@ -182,10 +191,29 @@ RUN --mount=type=cache,target=/var/lib/apt/lists \
182191
# -----------------------------------------------------------------------------
183192
# Create Non-Root User
184193
# -----------------------------------------------------------------------------
185-
# Create 'opencode' user with passwordless sudo
186-
RUN useradd -m -s /bin/bash -G sudo opencoder \
194+
# Create 'opencoder' user with passwordless sudo
195+
RUN set -eux; \
196+
# Create group first. Prefer requested GID; fall back if already in use. \
197+
if ! getent group opencoder >/dev/null; then \
198+
if getent group "${OPENCODER_GID}" >/dev/null; then \
199+
groupadd opencoder; \
200+
else \
201+
groupadd --gid "${OPENCODER_GID}" opencoder; \
202+
fi; \
203+
fi; \
204+
# Create user next. Prefer requested UID; fall back if already in use. \
205+
if ! id -u opencoder >/dev/null 2>&1; then \
206+
if getent passwd "${OPENCODER_UID}" >/dev/null; then \
207+
useradd -m -s /bin/bash --gid opencoder -G sudo opencoder; \
208+
else \
209+
useradd -m -s /bin/bash --uid "${OPENCODER_UID}" --gid opencoder -G sudo opencoder; \
210+
fi; \
211+
fi; \
212+
# Always pin the primary group to `opencoder` in case the user pre-existed. \
213+
usermod --gid opencoder opencoder \
187214
&& echo "opencoder ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/opencoder \
188215
&& chmod 0440 /etc/sudoers.d/opencoder \
216+
&& chmod 0750 /home/opencoder \
189217
# Snapshot built-in home users from the image so runtime auth logic can
190218
# ignore defaults (e.g. ubuntu) when deciding if onboarding should run.
191219
&& install -d -m 0755 /etc/opencode-cloud \
@@ -726,18 +754,14 @@ ENV PATH="/opt/opencode/bin:${PATH}"
726754
# This allows opencode to authenticate users via PAM (same users as Cockpit)
727755
# NOTE: Requires root privileges to write to /etc/pam.d/
728756
USER root
729-
COPY packages/core/src/docker/files/pam/opencode /etc/pam.d/opencode
730-
RUN chmod 644 /etc/pam.d/opencode
731-
732-
# Verify PAM config file exists
733-
RUN ls -la /etc/pam.d/opencode && cat /etc/pam.d/opencode
757+
COPY --chown=root:root --chmod=0644 packages/core/src/docker/files/pam/opencode /etc/pam.d/opencode
734758

735759
# -----------------------------------------------------------------------------
736760
# opencode-broker systemd Service
737761
# -----------------------------------------------------------------------------
738762
# Create opencode-broker service for PAM authentication
739763
# NOTE: Requires root privileges to write to /etc/systemd/system/
740-
COPY packages/core/src/docker/files/opencode-broker.service /etc/systemd/system/opencode-broker.service
764+
COPY --chown=root:root --chmod=0644 packages/core/src/docker/files/opencode-broker.service /etc/systemd/system/opencode-broker.service
741765

742766
# Enable opencode-broker service
743767
RUN mkdir -p /etc/systemd/system/multi-user.target.wants \
@@ -748,7 +772,7 @@ RUN mkdir -p /etc/systemd/system/multi-user.target.wants \
748772
# -----------------------------------------------------------------------------
749773
# Create opencode as a systemd service for Cockpit integration
750774
# NOTE: Requires root privileges to write to /etc/systemd/system/
751-
COPY packages/core/src/docker/files/opencode.service /etc/systemd/system/opencode.service
775+
COPY --chown=root:root --chmod=0644 packages/core/src/docker/files/opencode.service /etc/systemd/system/opencode.service
752776

753777
# Enable opencode service to start at boot (manual symlink since systemctl doesn't work during build)
754778
RUN mkdir -p /etc/systemd/system/multi-user.target.wants \
@@ -758,33 +782,25 @@ RUN mkdir -p /etc/systemd/system/multi-user.target.wants \
758782
# opencode Configuration
759783
# -----------------------------------------------------------------------------
760784
# Create opencode.jsonc config file with PAM authentication enabled
761-
RUN mkdir -p /home/opencoder/.config/opencode
762-
COPY --chown=opencoder:opencoder packages/core/src/docker/files/opencode.jsonc /home/opencoder/.config/opencode/opencode.jsonc
763-
RUN chown -R opencoder:opencoder /home/opencoder/.config/opencode \
764-
&& chmod 644 /home/opencoder/.config/opencode/opencode.jsonc
765-
766-
# Verify config file exists
767-
RUN ls -la /home/opencoder/.config/opencode/opencode.jsonc && cat /home/opencoder/.config/opencode/opencode.jsonc
785+
RUN install -d -o opencoder -g opencoder -m 0750 /home/opencoder/.config/opencode
786+
COPY --chown=opencoder:opencoder --chmod=0640 packages/core/src/docker/files/opencode.jsonc /home/opencoder/.config/opencode/opencode.jsonc
768787

769788
# -----------------------------------------------------------------------------
770789
# Entrypoint Script (Hybrid Init Support)
771790
# -----------------------------------------------------------------------------
772791
# Supports both tini (default, works everywhere) and systemd (for Cockpit on Linux)
773792
# Set USE_SYSTEMD=1 environment variable to use systemd init
774793
# Note: Entrypoint runs as root to support both modes; tini mode drops to opencode user
775-
COPY packages/core/src/docker/files/entrypoint.sh /usr/local/bin/entrypoint.sh
776-
RUN chmod +x /usr/local/bin/entrypoint.sh
794+
COPY --chown=root:root --chmod=0755 packages/core/src/docker/files/entrypoint.sh /usr/local/bin/entrypoint.sh
777795

778796
# Bootstrap helper for first-user onboarding (invoked by entrypoint and auth route via sudo)
779-
COPY packages/core/src/docker/files/opencode-cloud-bootstrap.sh /usr/local/bin/opencode-cloud-bootstrap
780-
RUN chmod 700 /usr/local/bin/opencode-cloud-bootstrap
797+
COPY --chown=root:root --chmod=0700 packages/core/src/docker/files/opencode-cloud-bootstrap.sh /usr/local/bin/opencode-cloud-bootstrap
781798

782799
# Note: Don't set USER here - entrypoint needs root to use runuser
783800
# The tini mode drops privileges to opencode user via runuser
784801

785802
# Healthcheck script asset
786-
COPY packages/core/src/docker/files/healthcheck.sh /usr/local/bin/healthcheck.sh
787-
RUN chmod +x /usr/local/bin/healthcheck.sh
803+
COPY --chown=root:root --chmod=0755 packages/core/src/docker/files/healthcheck.sh /usr/local/bin/healthcheck.sh
788804

789805
# -----------------------------------------------------------------------------
790806
# Health Check
@@ -800,8 +816,10 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
800816
COPY --from=opencode-build /opt/opencode /opt/opencode
801817
COPY --from=opencode-build /usr/local/bin/opencode-broker /usr/local/bin/opencode-broker
802818

803-
RUN chown -R opencoder:opencoder /opt/opencode \
819+
RUN chown -R root:root /opt/opencode \
820+
&& chmod -R go-w /opt/opencode \
804821
&& chmod +x /opt/opencode/bin/opencode \
822+
&& chown root:root /usr/local/bin/opencode-broker \
805823
&& chmod 4755 /usr/local/bin/opencode-broker
806824

807825
# Verify broker binary exists and is executable

0 commit comments

Comments
 (0)