diff --git a/.changeset/fix-docker-ca-certificates.md b/.changeset/fix-docker-ca-certificates.md new file mode 100644 index 0000000000..8794850250 --- /dev/null +++ b/.changeset/fix-docker-ca-certificates.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": patch +--- + +summary: Fix HTTPS git clones failing in Docker with "server certificate verification failed". +category: fix +dev: The runner stage installed `git` but not `ca-certificates`, and the slim base ships zero CA certificates. git verifies TLS against the SYSTEM trust store, so every HTTPS clone failed and project setup was impossible in a container. It stayed hidden because Node carries its own bundled CA store — the dashboard, model APIs, and OAuth token exchanges all worked. Guarded by a new assertion in scripts/__tests__/dockerfile-workspace-manifests.test.mjs. diff --git a/Dockerfile b/Dockerfile index 45fab37198..ebe5e200fe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -68,8 +68,14 @@ LABEL org.opencontainers.image.description="AI-orchestrated task board" ENV NODE_ENV=production ENV PORT=4040 +# FNXC:DockerRun 2026-08-18-05:35: ca-certificates is REQUIRED, not optional hardening. The slim +# base ships zero CA certificates, and git verifies TLS against the SYSTEM store — so every HTTPS +# clone failed with "server certificate verification failed. CAfile: none CRLfile: none", which +# breaks project setup outright (operator report). It hid behind Node, which carries its own bundled +# CA store: the dashboard, model APIs, and OAuth token exchanges all worked, so the image looked +# healthy right up until the first clone. RUN apt-get update \ - && apt-get install -y --no-install-recommends git \ + && apt-get install -y --no-install-recommends git ca-certificates \ && rm -rf /var/lib/apt/lists/* RUN corepack enable && corepack prepare pnpm@10.33.0 --activate diff --git a/scripts/__tests__/dockerfile-workspace-manifests.test.mjs b/scripts/__tests__/dockerfile-workspace-manifests.test.mjs index 05fd2ca160..ddebd56b6a 100644 --- a/scripts/__tests__/dockerfile-workspace-manifests.test.mjs +++ b/scripts/__tests__/dockerfile-workspace-manifests.test.mjs @@ -102,3 +102,28 @@ test("coverage ignores post-install and runner copies while tolerating removed p "removed or nonexistent COPY paths must not affect selected workspace coverage", ); }); + +/* +FNXC:DockerRun 2026-08-18-05:35: +The runner stage MUST install ca-certificates. The slim base ships none, and git verifies TLS +against the system store, so without it every HTTPS clone dies with "server certificate +verification failed. CAfile: none CRLfile: none" and project setup is impossible in Docker. + +This regressed unnoticed because Node carries its OWN bundled CA store: the dashboard, model APIs +and OAuth token exchanges all worked, so nothing looked wrong until the first clone. Nothing else +in the image exercises the system trust store, which is exactly why it needs a guard rather than +relying on someone noticing. +*/ +test("runner stage installs ca-certificates alongside git", () => { + const dockerfile = readFileSync(path.join(repoRoot, "Dockerfile"), "utf8"); + const runnerStage = dockerfile.slice(dockerfile.indexOf("FROM node:22-slim AS runner")); + assert.ok(runnerStage.length > 0, "runner stage must exist"); + + const aptInstall = runnerStage.match(/apt-get install[^\n]*(?:\\\n[^\n]*)*/)?.[0] ?? ""; + assert.match(aptInstall, /\bgit\b/, "runner stage must install git"); + assert.match( + aptInstall, + /\bca-certificates\b/, + "runner stage must install ca-certificates — git cannot verify HTTPS remotes without a system CA bundle", + ); +});