Summary
Dockerfile:47 fetches and executes the Bun installer from https://bun.sh/install with no version pin, checksum, or signature verification:
```dockerfile
if curl --retry 5 --retry-all-errors --retry-delay 2 -fsSL https://bun.sh/install | bash; then
```
This is inconsistent with how every other base image in the same Dockerfile is handled. Lines 15–16 pin both Node images to SHA256 digests:
```dockerfile
ARG OPENCLAW_NODE_BOOKWORM_IMAGE="node:24-bookworm@sha256:3a09aa6354..."
ARG OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE="node:24-bookworm-slim@sha256:e8e2e91b..."
```
Impact
If bun.sh or its CDN is compromised (DNS hijack, CDN takeover, or domain compromise), every Docker image build silently installs and executes attacker-controlled code as root inside the build container. Any CI/CD pipeline rebuilding this image becomes a supply chain vector — the malicious binary ends up in the final runtime image shipped to users.
The retry loop (attempts 1–5) makes this worse: a partial compromise that returns a malicious script on retry 2 would still succeed.
Correct version
.github/actions/setup-node-env/action.yml:50 pins Bun to 1.3.9 via oven-sh/setup-bun@v2.2.0. The Dockerfile should use the same version.
Fix
Replace the curl | bash block with a multi-stage COPY from the official Bun image, keeping the version in sync with CI:
```dockerfile
ARG BUN_VERSION=1.3.9
... other stages ...
FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS build
ARG BUN_VERSION
COPY --from=oven/bun:${BUN_VERSION} /usr/local/bin/bun /usr/local/bin/bun
```
Remove the existing RUN set -eux; for attempt in ... block and the ENV PATH="/root/.bun/bin:${PATH}" line (no longer needed since /usr/local/bin is already on PATH).
For full parity with the Node image pinning strategy, the oven/bun image should also be pinned to a SHA256 digest and updated via Dependabot alongside the Node digests.
Affected file
Summary
Dockerfile:47fetches and executes the Bun installer fromhttps://bun.sh/installwith no version pin, checksum, or signature verification:```dockerfile
if curl --retry 5 --retry-all-errors --retry-delay 2 -fsSL https://bun.sh/install | bash; then
```
This is inconsistent with how every other base image in the same Dockerfile is handled. Lines 15–16 pin both Node images to SHA256 digests:
```dockerfile
ARG OPENCLAW_NODE_BOOKWORM_IMAGE="node:24-bookworm@sha256:3a09aa6354..."
ARG OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE="node:24-bookworm-slim@sha256:e8e2e91b..."
```
Impact
If
bun.shor its CDN is compromised (DNS hijack, CDN takeover, or domain compromise), every Docker image build silently installs and executes attacker-controlled code as root inside the build container. Any CI/CD pipeline rebuilding this image becomes a supply chain vector — the malicious binary ends up in the final runtime image shipped to users.The retry loop (attempts 1–5) makes this worse: a partial compromise that returns a malicious script on retry 2 would still succeed.
Correct version
.github/actions/setup-node-env/action.yml:50pins Bun to1.3.9viaoven-sh/setup-bun@v2.2.0. The Dockerfile should use the same version.Fix
Replace the
curl | bashblock with a multi-stageCOPYfrom the official Bun image, keeping the version in sync with CI:```dockerfile
ARG BUN_VERSION=1.3.9
... other stages ...
FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS build
ARG BUN_VERSION
COPY --from=oven/bun:${BUN_VERSION} /usr/local/bin/bun /usr/local/bin/bun
```
Remove the existing
RUN set -eux; for attempt in ...block and theENV PATH="/root/.bun/bin:${PATH}"line (no longer needed since/usr/local/binis already on PATH).For full parity with the Node image pinning strategy, the
oven/bunimage should also be pinned to a SHA256 digest and updated via Dependabot alongside the Node digests.Affected file
Dockerfile:43–55