Skip to content

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

Merged
sallyom merged 4 commits intoopenclaw:mainfrom
fede-kamel:fix/bun-curl-pipe
May 2, 2026
Merged

fix(docker): replace curl|bash Bun install with pinned multi-stage COPY#74359
sallyom merged 4 commits intoopenclaw:mainfrom
fede-kamel:fix/bun-curl-pipe

Conversation

@fede-kamel
Copy link
Copy Markdown
Contributor

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/setup-bun@v2.2.0. 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.

@openclaw-barnacle openclaw-barnacle Bot added docker Docker and sandbox tooling size: XS labels Apr 29, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 29, 2026

Greptile Summary

This PR eliminates the curl | bash Bun installation by replacing it with a pinned multi-stage COPY --from the official oven/bun:1.3.9 image, bringing the Bun bootstrap in line with how other base images are consumed. The change is correct and materially improves supply-chain safety; the only gap is that oven/bun:1.3.9 is referenced by mutable tag rather than SHA256 digest, which the PR author has already flagged as a follow-up item.

Confidence Score: 4/5

Safe to merge; the supply-chain improvement is sound and the only finding is a missing SHA256 digest already acknowledged as a follow-up.

Single P2 finding (missing digest pin on the new bun image) that the PR author has already called out. No logic errors, no security regressions relative to the prior state.

Dockerfile line 19 — consider adding a SHA256 digest to OPENCLAW_BUN_IMAGE before the follow-up PR.

Prompt To Fix All With AI
This is a comment left during a code review.
Path: Dockerfile
Line: 19

Comment:
**Bun image not pinned to a SHA256 digest**

`oven/bun:1.3.9` is referenced by mutable tag only. The Dockerfile's own stated policy (lines 21–26) is that all base images are pinned to SHA256 digests for reproducible builds and supply-chain integrity. Without a digest, Docker will silently pull a different layer if the tag is ever retagged on Docker Hub, which partially undermines the goal of this PR. The PR description calls this out as a follow-up, but adding the digest now would be consistent with how the Node images are handled.

Run `docker buildx imagetools inspect oven/bun:1.3.9` to obtain the correct multi-arch manifest digest.

```suggestion
ARG OPENCLAW_BUN_IMAGE="oven/bun:1.3.9@sha256:<digest>"
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(docker): replace curl|bash Bun insta..." | Re-trigger Greptile

Comment thread Dockerfile Outdated
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented Apr 29, 2026

Codex review: found issues before merge.

Summary
The PR removes the root Dockerfile Bun curl-pipe installer, copies Bun 1.3.13 from a digest-pinned oven/bun source stage, extends Docker digest coverage, and adds a changelog entry.

Reproducibility: yes. Static inspection of current main reproduces the reported condition: the root Dockerfile still executes https://bun.sh/install through bash during the Docker build stage.

Next step before merge
Maintainer/security approval and Docker build proof are the remaining steps; a replacement or automated repair PR is not the right lane for this active, mergeable contributor PR.

Security
Cleared: The diff improves Docker supply-chain posture by removing build-time remote shell execution and using a digest-pinned Bun image; no concrete new security regression was found.

Review findings

  • [P3] Limit ARG defaults to Docker global scope — src/docker-image-digests.test.ts:38-45
Review details

Best possible solution:

Land this Docker hardening after maintainer/security approval and Docker build proof, then handle docs-example hardening separately if maintainers want the policy to cover copy-paste examples.

Do we have a high-confidence way to reproduce the issue?

Yes. Static inspection of current main reproduces the reported condition: the root Dockerfile still executes https://bun.sh/install through bash during the Docker build stage.

Is this the best way to solve the issue?

Yes, with a non-blocking test-helper caveat. Copying Bun from a digest-pinned official image aligned with CI is the narrow maintainable fix for the live Dockerfile risk; the digest helper should model Docker ARG scope more precisely for future coverage.

Full review comments:

  • [P3] Limit ARG defaults to Docker global scope — src/docker-image-digests.test.ts:38-45
    resolveArgDefaults now collects ARG defaults from the entire Dockerfile, but Docker only lets FROM use ARGs declared before the first FROM. A future stage-local ARG FOO=... plus FROM $FOO would make this test resolve a value Docker would not resolve, so keep the resolver scoped to global ARGs or model Docker ARG scope explicitly.
    Confidence: 0.74

Overall correctness: patch is correct
Overall confidence: 0.88

Acceptance criteria:

  • pnpm test src/docker-image-digests.test.ts
  • pnpm check:changed in Testbox before merge
  • Root Docker image build or Docker install-smoke lane that exercises the bun-binary source stage

What I checked:

  • Current main still has the reported runtime pattern: The root Dockerfile on current main still installs Bun by piping https://bun.sh/install into bash during the build stage and prepends /root/.bun/bin to PATH. (Dockerfile:47, dda2db97d43b)
  • PR removes curl-pipe Bun installation: Latest PR head defines OPENCLAW_BUN_IMAGE as oven/bun:1.3.13@sha256:87416c977a612a204eb54ab9f3927023c2a3c971f4f345a01da08ea6262ae30e, adds a bun-binary stage, and copies /usr/local/bin/bun into the build stage. (Dockerfile:20, 3b4a88946720)
  • Bun version aligned with CI: Current main's shared setup action pins bun-version: "1.3.13", matching the PR's Docker Bun image tag. (.github/actions/setup-node-env/action.yml:50, dda2db97d43b)
  • Digest test coverage widened: The PR adds a check for all ARG-backed FROM stages, so the new bun-binary source stage is covered by the sha256 digest assertion. (src/docker-image-digests.test.ts:111, 3b4a88946720)
  • Docker ARG scope caveat: Docker's Dockerfile reference says FROM instructions support variables declared by ARG instructions before the first FROM; the new helper scans ARG defaults across the whole file, which can over-model future stage-local ARGs. (src/docker-image-digests.test.ts:38, 3b4a88946720)
  • Exact-head checks settled: GitHub check-runs for PR head 3b4a889467208ef578e1ab141977c11361a20829 reported 77 success, 8 skipped, and 1 neutral check, with no failing or pending check-runs in the unauthenticated API result. (3b4a88946720)

Likely related people:

  • steipete: Recent path history shows repeated maintenance of the root Dockerfile, shared setup action, and Docker digest test surface that this PR touches. (role: recent Docker and CI maintainer; confidence: high; commits: ed8f50f240a8, aa84b738b6ea, a3bbcf2792b1; files: Dockerfile, .github/actions/setup-node-env/action.yml, src/docker-image-digests.test.ts)
  • sallyom: Recent main history includes Docker container build work, and the latest PR head commit aligning Bun 1.3.13 and the changelog was authored by this maintainer. (role: recent Docker maintainer and PR branch maintainer; confidence: high; commits: 57f19f0d5c10, e8258fd4a6eb, 3b4a88946720; files: Dockerfile, src/docker-image-digests.test.ts, CHANGELOG.md)
  • loukotal: Merged PR fix: install Bun in Dockerfile #284 added the original Bun installer block so Docker builds could run Bun-backed build scripts. (role: introduced Bun-in-Dockerfile behavior; confidence: medium; commits: c16510c6ea46; files: Dockerfile)
  • coygeek: Commit 8ae2d5110f6c pinned Docker base images, added Dependabot Docker coverage, and introduced the digest regression test that this PR extends. (role: digest-pinning policy contributor; confidence: medium; commits: 8ae2d5110f6c; files: Dockerfile, .github/dependabot.yml, src/docker-image-digests.test.ts)

Remaining risk / open question:

  • A real root Docker image build or install-smoke was not run in this read-only review, so the copied Bun binary still needs runtime proof across supported platforms.
  • docs/install/docker.md still has a power-user example using curl -fsSL https://bun.sh/install | bash; that may need a separate docs hardening follow-up if examples are in scope.

Codex review notes: model gpt-5.5, reasoning high; reviewed against dda2db97d43b.

@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented Apr 29, 2026

Codex review: needs maintainer review before merge.

What this changes:

The PR updates the root Dockerfile to copy Bun 1.3.9 from a digest-pinned oven/bun source stage and extends src/docker-image-digests.test.ts to validate every ARG-backed FROM stage.

Maintainer follow-up before merge:

This is an active external-contributor PR touching Docker supply-chain hardening; the remaining action is maintainer/security review plus CI and Docker build validation, not an automated replacement branch.

Review details

Best possible solution:

Land a reviewed Docker hardening change that removes build-time execution of the remote Bun installer, keeps the Bun source image digest-pinned and aligned with the CI Bun version, validates all ARG-backed Docker stages, and closes #74356 through the merge after CI and Docker build proof pass.

Acceptance criteria:

  • pnpm test src/dockerfile.test.ts src/docker-image-digests.test.ts
  • pnpm check:changed in Testbox before merge
  • Root Docker image build or Docker install-smoke lane that exercises the new bun-binary source stage

What I checked:

  • Current main still runs the remote Bun installer: The root Dockerfile currently installs Bun by piping https://bun.sh/install into bash and prepending /root/.bun/bin to PATH. (Dockerfile:47, e46dccb35374)
  • PR removes curl-pipe install from the build stage: The latest PR diff adds FROM ${OPENCLAW_BUN_IMAGE} AS bun-binary and copies /usr/local/bin/bun into the Node build stage instead of executing the installer script. (Dockerfile:43, 9d7a9dc9141d)
  • Bun image digest is pinned and matches the registry manifest list: docker buildx imagetools inspect oven/bun:1.3.9 reports digest sha256:856da45d07aeb62eb38ea3e7f9e1794c0143a4ff63efb00e6c4491b627e2a521, matching the PR's OPENCLAW_BUN_IMAGE value. (Dockerfile:20, 9d7a9dc9141d)
  • CI Bun version anchor matches the PR version: The shared setup action installs Bun 1.3.9, which matches the image tag selected by the PR. (.github/actions/setup-node-env/action.yml:50, e46dccb35374)
  • Digest test coverage is widened for ARG-backed stages: The PR adds resolveAllArgBackedFromReferences and a test that checks all ARG-backed FROM stages, so the new bun-binary stage is covered by the digest assertion. (src/docker-image-digests.test.ts:108, 9d7a9dc9141d)
  • Paired issue remains open: The PR body uses closing syntax for Dockerfile: Bun installed via unverified curl | bash while Node base images are SHA256-pinned #74356, and that report is still open, so the issue should remain paired until this PR is merged or closed.

Likely related people:

  • steipete: Recent GitHub commit history for Dockerfile and the shared setup action shows repeated Docker/runtime and CI maintenance around the affected build surface. (role: recent Docker and CI maintainer; confidence: medium; commits: aa84b738b6ea, b04c9380ed63, a3bbcf2792b1; files: Dockerfile, .github/actions/setup-node-env/action.yml, docs/install/docker.md)
  • loukotal: Merged PR fix: install Bun in Dockerfile #284 added the original Bun installer block to the Dockerfile so Docker builds could run Bun-backed build scripts. (role: introduced Bun-in-Dockerfile behavior; confidence: medium; commits: c16510c6ea46; files: Dockerfile)
  • coygeek: Commit 8ae2d5110f6c pinned Docker base images, added Dependabot Docker coverage, and introduced the digest regression test that this PR extends. (role: digest-pinning policy contributor; confidence: medium; commits: 8ae2d5110f6c; files: Dockerfile, .github/dependabot.yml, src/docker-image-digests.test.ts)

Remaining risk / open question:

  • The latest head still had queued CI checks at review time, including lint/type/build-artifact checks.
  • A real root Docker image build or install-smoke was not run in this read-only review, so maintainers should still validate that the copied Bun binary works in the Node bookworm build stage across supported platforms.
  • docs/install/docker.md:364 still contains a power-user Dockerfile example using curl -fsSL https://bun.sh/install | bash; that may need a follow-up if the hardening policy should also cover docs examples.

Codex review notes: model gpt-5.5, reasoning high; reviewed against e46dccb35374.

@fede-kamel fede-kamel force-pushed the fix/bun-curl-pipe branch 3 times, most recently from e352890 to 6cb9a66 Compare April 29, 2026 17:28
@openclaw-barnacle openclaw-barnacle Bot added the gateway Gateway runtime label Apr 29, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the gateway Gateway runtime label Apr 29, 2026
@fede-kamel fede-kamel force-pushed the fix/bun-curl-pipe branch 2 times, most recently from 12efc4e to 8f748b8 Compare April 30, 2026 16:06
fede-kamel added 3 commits May 2, 2026 10:20
The previous approach fetched https://bun.sh/install and executed it as
root with no version pin, checksum, or signature verification — despite
both Node base images being pinned to SHA256 digests.

Replace with a multi-stage COPY from the official oven/bun image, using
the same version (1.3.9) already pinned in
.github/actions/setup-node-env/action.yml. The new OPENCLAW_BUN_IMAGE
ARG follows the same pattern as OPENCLAW_NODE_BOOKWORM_IMAGE and can be
updated via Dependabot.

Closes openclaw#74356
The existing check only validated the first FROM line. The new bun-binary
stage (FROM ${OPENCLAW_BUN_IMAGE}) would have been invisible to it.

Add resolveAllArgBackedFromReferences that walks every FROM line and
resolves ARG-backed image references, so all pinned base stages are
checked — not just the first one.
@sallyom sallyom force-pushed the fix/bun-curl-pipe branch from 8f748b8 to 8823ff3 Compare May 2, 2026 14:24
@sallyom sallyom force-pushed the fix/bun-curl-pipe branch from 8823ff3 to 3b4a889 Compare May 2, 2026 14:28
@sallyom sallyom self-assigned this May 2, 2026
@sallyom
Copy link
Copy Markdown
Contributor

sallyom commented May 2, 2026

Thanks for this PR! I've updated CI and Dockerfile to latest Bun v1.3.13.

@sallyom sallyom merged commit 10ebcbd into openclaw:main May 2, 2026
86 checks passed
@sallyom
Copy link
Copy Markdown
Contributor

sallyom commented May 2, 2026

Merged. Prepared head: 3b4a889. Merge commit: 10ebcbd.

@fede-kamel fede-kamel deleted the fix/bun-curl-pipe branch May 2, 2026 15:09
lxe pushed a commit to lxe/openclaw that referenced this pull request May 6, 2026
…PY (openclaw#74359)

Merged via squash.

Prepared head SHA: 3b4a889
Co-authored-by: fede-kamel <209537060+fede-kamel@users.noreply.github.com>
Co-authored-by: sallyom <11166065+sallyom@users.noreply.github.com>
Reviewed-by: @sallyom
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…PY (openclaw#74359)

Merged via squash.

Prepared head SHA: 3b4a889
Co-authored-by: fede-kamel <209537060+fede-kamel@users.noreply.github.com>
Co-authored-by: sallyom <11166065+sallyom@users.noreply.github.com>
Reviewed-by: @sallyom
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docker Docker and sandbox tooling size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dockerfile: Bun installed via unverified curl | bash while Node base images are SHA256-pinned

2 participants