fix(security): keep the git checkout out of the published image - #13
Merged
Conversation
`COPY . .` with no `.dockerignore` baked the entire build context into the image layer, including `.git`. `actions/checkout` defaults to `persist-credentials: true`, which writes the job's ephemeral `GITHUB_TOKEN` into `.git/config` as `http.extraheader`, so every published image shipped a copy of that token — readable by anyone who pulled the image while the token was still valid. - Dockerfile: copy only `deno.json`/`deno.lock` (before `deno install`, which also keeps the dependency layer cached) and `src/index.ts`. - Add a deny-all `.dockerignore` allow-listing those same paths, so a future `COPY . .` cannot reintroduce the leak. - Set `persist-credentials: false` on every checkout; no job needs git credentials after checkout. This also stops `.env.local`, the test suite and the TLS test fixtures (including `src/fixtures/tls/key.pem`) from being shipped.
IKatsuba
force-pushed
the
fix/docker-context-credential-leak
branch
from
August 8, 2026 21:31
dbae7a6 to
359c6de
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.
Problem
The
DockerfileusedCOPY . .and the repository had no.dockerignore, so the whole build context landed in an image layer — including.git.actions/checkoutdefaults topersist-credentials: true, which writes the job's ephemeralGITHUB_TOKENinto.git/config:So every published image carried that token, readable by anyone who pulled the image while the token was still valid — a window running from the image push to the end of the publish job. In that window the token grants
packages: writeonghcr.io/ikatsuba/*(thepublishjob scopes its permissions, so it is not the full default set).Confirmed present in
ghcr.io/ikatsuba/nx-cache-server:main. Tokens in already-published images are expired, so there is nothing to rotate.The same
COPY . .also shipped.env.local, the test suites,.github/, editor configs, and — on any build after #11 — the TLS test fixtures includingsrc/fixtures/tls/key.pem.Fix
Dockerfile— copy onlydeno.json/deno.lock(ahead ofdeno install, which also keeps the dependency layer cached) andsrc/index.ts..dockerignore(new) — deny-all plus an allow-list of those same paths, so a futureCOPY . .cannot reintroduce the leak..github/workflows/main.yml—persist-credentials: falseon all five checkout steps. No job needs git credentials after checkout;helm-publishauthenticates to GHCR explicitly.Verification
/appcontains onlydeno.json,deno.lock,src/index.ts. Agrepacross the filesystem forextraheaderand the test AWS key returns nothing.GET /healthreturns200.deno fmt --checkanddeno lintpass.Reported privately by email. Follow-up worth doing separately: add a
SECURITY.mdso reports have a documented channel.