openclaw - ✅(Solved) Fix Dockerfile: Bun installed via unverified curl | bash while Node base images are SHA256-pinned [1 pull requests, 2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#74356Fetched 2026-04-30 06:25:03
View on GitHub
Comments
2
Participants
2
Timeline
9
Reactions
2
Timeline (top)
referenced ×6commented ×2cross-referenced ×1

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..." ```

Root Cause

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..." ```

Fix Action

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.

PR fix notes

PR #74359: fix(docker): replace curl|bash Bun install with pinned multi-stage COPY

Description (problem / solution / changelog)

Closes #74356

What changed

Dockerfile:43–55 previously bootstrapped Bun by fetching https://bun.sh/install and piping it directly to bash with no version pin, checksum, or signature verification:

# before
RUN set -eux; \
    for attempt in 1 2 3 4 5; do \
      if curl --retry 5 --retry-all-errors --retry-delay 2 -fsSL https://bun.sh/install | bash; then \
        break; \
      ...
ENV PATH="/root/.bun/bin:${PATH}"

Replaced with a pinned multi-stage COPY from the official oven/bun image:

# after
ARG OPENCLAW_BUN_IMAGE="oven/bun:1.3.9"
...
FROM ${OPENCLAW_BUN_IMAGE} AS bun-binary
FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS build
COPY --from=bun-binary /usr/local/bin/bun /usr/local/bin/bun

Why

All other base images are pinned to SHA256 digests. The curl | bash approach bypassed this: a DNS hijack or CDN compromise of bun.sh during any Docker build would execute attacker code as root and ship the result in the final image.

Version choice

1.3.9 matches the version already pinned in .github/actions/setup-node-env/action.yml:50 via oven-sh/[email protected]. The new OPENCLAW_BUN_IMAGE ARG follows the same override pattern as the Node image args.

Follow-up (not in this PR)

Pin oven/bun:1.3.9 to a SHA256 digest and add it to the Dependabot config alongside the Node image digests.

Changed files

  • Dockerfile (modified, +6/-13)
  • src/docker-image-digests.test.ts (modified, +54/-18)
RAW_BUFFERClick to expand / collapse

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/[email protected]. 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

  • Dockerfile:43–55

extent analysis

TL;DR

Replace the curl | bash block in the Dockerfile with a multi-stage COPY from the official Bun image to ensure version consistency and security.

Guidance

  • Pin the Bun version to 1.3.9 in the Dockerfile to match the version used in the CI setup.
  • Use a multi-stage COPY to copy the bun binary from the official Bun image, ensuring the version is consistent with the CI setup.
  • Remove the existing RUN block and ENV line that are no longer needed after the change.
  • Consider pinning the oven/bun image to a SHA256 digest for added security and update it via Dependabot alongside the Node digests.

Example

ARG BUN_VERSION=1.3.9
...
FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS build
ARG BUN_VERSION
COPY --from=oven/bun:${BUN_VERSION} /usr/local/bin/bun /usr/local/bin/bun

Notes

This fix assumes that the oven/bun image is available and up-to-date. It's also important to note that pinning the oven/bun image to a SHA256 digest is recommended for added security, but it's not included in the provided fix.

Recommendation

Apply the workaround by replacing the curl | bash block with the multi-stage COPY approach to ensure version consistency and security. This approach provides a more secure way to install Bun in the Docker image.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Dockerfile: Bun installed via unverified curl | bash while Node base images are SHA256-pinned [1 pull requests, 2 comments, 2 participants]