Keep the npm build token out of builder-stage layers#52
Merged
chiro-hiro merged 1 commit intoJun 4, 2026
Merged
Conversation
Previously the credentials (.npmrc/.yarnrc.yml) were written in a dedicated builder RUN and never removed, so the npm token persisted in a builder-stage layer and the builder image filesystem (recoverable by anyone who can pull or run that stage / exported build cache). Now the credentials are created, used, and deleted inside the single build RUN (under --mount=type=secret,mode=0444), so they exist only for the duration of that one layer's execution and are gone from the resulting layer: - Dockerfile.template: the first builder RUN only prepares the home/workdir; it no longer writes credentials. - dockerfile.sh generate_build_command: emits a secret-mounted RUN that writes the .npmrc/.yarnrc.yml, runs the build, and removes them (set -e aborts the RUN on build failure, so no layer is committed). Verified by building the builder stage with a canary secret: the token is present in the builder image filesystem with the old pattern and absent with the new one. Enforced going forward by a new CI job (builder-secret-no-leak). SECURITY.md updated (no longer a known limitation); CHANGELOG updated; checksum.sha256 regenerated.
14c81cd to
0271ad9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #51
Problem
In the current template, the npm credentials (
.npmrc/.yarnrc.yml) are written in a dedicated builderRUNand never removed, so the token persists in a builder-stage layer and in the builder image filesystem — recoverable by anyone who can pull/run that stage or an exported build cache (--target builder,--cache-to mode=max). The BuildKit secret mount keeps the token out of the build context, but copying it into a real file re-introduces it into a layer.Fix
Create, use, and delete the credentials inside the single build
RUN(under--mount=type=secret,mode=0444), so they only exist for that one layer's execution and leave no trace in the resulting layer:Dockerfile.template— the first builderRUNnow only prepares the home/workdir; it no longer writes credentials.dockerfile.sh(generate_build_command) — emits a secret-mountedRUNthat writes.npmrc/.yarnrc.yml, runs the build, thenrm -fs them.set -eaborts the RUN on build failure, so no partial layer is committed.mode=0444lets the non-root builder user read the mounted secret.Credential content and scopes (
orochi-network,zkdb) are unchanged, so build behavior is identical for consumers; the secret-mount requirement (BuildKit) is unchanged from the previous template.Verification
Built the builder stage (
--target builder) with a canary secret, old vs new:main)/home/ubuntu/.npmrc✗For the new single-
RUNpattern, "absent from the final builder filesystem" equals "absent from every layer" by Docker's layer-diff semantics (one RUN creates and deletes the files → the layer diff contains neither).Enforced in CI: new
builder-secret-no-leakjob builds the builder stage with a canary secret and fails if the token is found in the builder image. (orochinetwork/ubuntu:nodeis public, so CI can pull it; the secret is a throwaway literal.)SECURITY.mdupdated (no longer a known limitation),CHANGELOG.mdupdated,checksum.sha256regenerated.